BasicValueFactory.h revision 226633
141502Swpaul//=== BasicValueFactory.h - Basic values for Path Sens analysis --*- C++ -*---//
241502Swpaul//
341502Swpaul//                     The LLVM Compiler Infrastructure
441502Swpaul//
541502Swpaul// This file is distributed under the University of Illinois Open Source
641502Swpaul// License. See LICENSE.TXT for details.
741502Swpaul//
841502Swpaul//===----------------------------------------------------------------------===//
941502Swpaul//
1041502Swpaul//  This file defines BasicValueFactory, a class that manages the lifetime
1141502Swpaul//  of APSInt objects and symbolic constraints used by ExprEngine
1241502Swpaul//  and related classes.
1341502Swpaul//
1441502Swpaul//===----------------------------------------------------------------------===//
1541502Swpaul
1641502Swpaul#ifndef LLVM_CLANG_GR_BASICVALUEFACTORY_H
1741502Swpaul#define LLVM_CLANG_GR_BASICVALUEFACTORY_H
1841502Swpaul
1941502Swpaul#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
2041502Swpaul#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
2141502Swpaul#include "clang/AST/ASTContext.h"
2241502Swpaul#include "llvm/ADT/FoldingSet.h"
2341502Swpaul#include "llvm/ADT/APSInt.h"
2441502Swpaul#include "llvm/ADT/ImmutableList.h"
2541502Swpaul
2641502Swpaulnamespace clang {
2741502Swpaul
2841502Swpaulnamespace ento {
2941502Swpaul
3041502Swpaulclass ProgramState;
3141502Swpaul
3241502Swpaulclass CompoundValData : public llvm::FoldingSetNode {
3341502Swpaul  QualType T;
3441502Swpaul  llvm::ImmutableList<SVal> L;
3541502Swpaul
3641502Swpaulpublic:
3741502Swpaul  CompoundValData(QualType t, llvm::ImmutableList<SVal> l)
3841502Swpaul    : T(t), L(l) {}
3941502Swpaul
4041502Swpaul  typedef llvm::ImmutableList<SVal>::iterator iterator;
4141502Swpaul  iterator begin() const { return L.begin(); }
4241502Swpaul  iterator end() const { return L.end(); }
4341502Swpaul
4441502Swpaul  static void Profile(llvm::FoldingSetNodeID& ID, QualType T,
4541502Swpaul                      llvm::ImmutableList<SVal> L);
4641502Swpaul
4741502Swpaul  void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, T, L); }
4841502Swpaul};
4941502Swpaul
5041502Swpaulclass LazyCompoundValData : public llvm::FoldingSetNode {
5141502Swpaul  StoreRef store;
5241502Swpaul  const TypedValueRegion *region;
5341502Swpaulpublic:
5441502Swpaul  LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r)
5541502Swpaul    : store(st), region(r) {}
5641502Swpaul
5741502Swpaul  const void *getStore() const { return store.getStore(); }
5841502Swpaul  const TypedValueRegion *getRegion() const { return region; }
5941502Swpaul
6041502Swpaul  static void Profile(llvm::FoldingSetNodeID& ID,
6141502Swpaul                      const StoreRef &store,
6241502Swpaul                      const TypedValueRegion *region);
6341502Swpaul
6441502Swpaul  void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); }
6541502Swpaul};
6641502Swpaul
6741502Swpaulclass BasicValueFactory {
6841502Swpaul  typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
6941502Swpaul          APSIntSetTy;
7041502Swpaul
7141502Swpaul  ASTContext &Ctx;
7241502Swpaul  llvm::BumpPtrAllocator& BPAlloc;
7341502Swpaul
7441502Swpaul  APSIntSetTy   APSIntSet;
7541502Swpaul  void *        PersistentSVals;
7641502Swpaul  void *        PersistentSValPairs;
7741502Swpaul
7841502Swpaul  llvm::ImmutableList<SVal>::Factory SValListFactory;
7941502Swpaul  llvm::FoldingSet<CompoundValData>  CompoundValDataSet;
8041502Swpaul  llvm::FoldingSet<LazyCompoundValData> LazyCompoundValDataSet;
8141502Swpaul
8241502Swpaulpublic:
8341502Swpaul  BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator& Alloc)
84113038Sobrien  : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(0), PersistentSValPairs(0),
85113038Sobrien    SValListFactory(Alloc) {}
86113038Sobrien
8748745Swpaul  ~BasicValueFactory();
8841502Swpaul
8941502Swpaul  ASTContext &getContext() const { return Ctx; }
9041502Swpaul
9141502Swpaul  const llvm::APSInt& getValue(const llvm::APSInt& X);
9241502Swpaul  const llvm::APSInt& getValue(const llvm::APInt& X, bool isUnsigned);
9341502Swpaul  const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
9441502Swpaul  const llvm::APSInt& getValue(uint64_t X, QualType T);
9541502Swpaul
9650675Swpaul  /// Convert - Create a new persistent APSInt with the same value as 'From'
9741502Swpaul  ///  but with the bitwidth and signedness of 'To'.
9841502Swpaul  const llvm::APSInt &Convert(const llvm::APSInt& To,
9941502Swpaul                              const llvm::APSInt& From) {
10041502Swpaul
10141502Swpaul    if (To.isUnsigned() == From.isUnsigned() &&
10241502Swpaul        To.getBitWidth() == From.getBitWidth())
10341502Swpaul      return From;
10441502Swpaul
10541502Swpaul    return getValue(From.getSExtValue(), To.getBitWidth(), To.isUnsigned());
10641502Swpaul  }
10741502Swpaul
10841502Swpaul  const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {
10941502Swpaul    assert(T->isIntegerType() || Loc::isLocType(T));
11041502Swpaul    unsigned bitwidth = Ctx.getTypeSize(T);
11149611Swpaul    bool isUnsigned
11249611Swpaul      = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T);
11349611Swpaul
11441502Swpaul    if (isUnsigned == From.isUnsigned() && bitwidth == From.getBitWidth())
11541502Swpaul      return From;
11641502Swpaul
11741502Swpaul    return getValue(From.getSExtValue(), bitwidth, isUnsigned);
11850675Swpaul  }
11950675Swpaul
12050675Swpaul  const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) {
12151089Speter    QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy;
12250675Swpaul    return getValue(X, T);
12350675Swpaul  }
12441502Swpaul
12541502Swpaul  inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) {
12641502Swpaul    return getValue(llvm::APSInt::getMaxValue(v.getBitWidth(), v.isUnsigned()));
12741502Swpaul  }
128113506Smdodd
129113506Smdodd  inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) {
13059758Speter    return getValue(llvm::APSInt::getMinValue(v.getBitWidth(), v.isUnsigned()));
13159758Speter  }
13241502Swpaul
13341502Swpaul  inline const llvm::APSInt& getMaxValue(QualType T) {
13441502Swpaul    assert(T->isIntegerType() || Loc::isLocType(T));
13541502Swpaul    bool isUnsigned
13641502Swpaul      = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T);
13741502Swpaul    return getValue(llvm::APSInt::getMaxValue(Ctx.getTypeSize(T), isUnsigned));
13841502Swpaul  }
13941502Swpaul
14041502Swpaul  inline const llvm::APSInt& getMinValue(QualType T) {
14141502Swpaul    assert(T->isIntegerType() || Loc::isLocType(T));
14241502Swpaul    bool isUnsigned
14392739Salfred      = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T);
14492739Salfred    return getValue(llvm::APSInt::getMinValue(Ctx.getTypeSize(T), isUnsigned));
14592739Salfred  }
14641502Swpaul
14798995Salfred  inline const llvm::APSInt& Add1(const llvm::APSInt& V) {
14892739Salfred    llvm::APSInt X = V;
14948745Swpaul    ++X;
15092739Salfred    return getValue(X);
15192739Salfred  }
15292739Salfred
15341502Swpaul  inline const llvm::APSInt& Sub1(const llvm::APSInt& V) {
15492739Salfred    llvm::APSInt X = V;
15592739Salfred    --X;
15692739Salfred    return getValue(X);
15792739Salfred  }
15892739Salfred
15992739Salfred  inline const llvm::APSInt& getZeroWithPtrWidth(bool isUnsigned = true) {
16092739Salfred    return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned);
16192739Salfred  }
16292739Salfred
16392739Salfred  inline const llvm::APSInt &getIntWithPtrWidth(uint64_t X, bool isUnsigned) {
16492739Salfred    return getValue(X, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned);
16592739Salfred  }
16692739Salfred
16792739Salfred  inline const llvm::APSInt& getTruthValue(bool b, QualType T) {
16841502Swpaul    return getValue(b ? 1 : 0, Ctx.getTypeSize(T), false);
16992739Salfred  }
17092739Salfred
17192739Salfred  inline const llvm::APSInt& getTruthValue(bool b) {
17292739Salfred    return getTruthValue(b, Ctx.getLogicalOperationType());
17392739Salfred  }
17492739Salfred
17592739Salfred  const CompoundValData *getCompoundValData(QualType T,
17641502Swpaul                                            llvm::ImmutableList<SVal> Vals);
17792739Salfred
17892739Salfred  const LazyCompoundValData *getLazyCompoundValData(const StoreRef &store,
17992739Salfred                                            const TypedValueRegion *region);
18092739Salfred
18192739Salfred  llvm::ImmutableList<SVal> getEmptySValList() {
18292739Salfred    return SValListFactory.getEmptyList();
18392739Salfred  }
18441502Swpaul
18592739Salfred  llvm::ImmutableList<SVal> consVals(SVal X, llvm::ImmutableList<SVal> L) {
18692739Salfred    return SValListFactory.add(X, L);
18792739Salfred  }
18850675Swpaul
18949611Swpaul  const llvm::APSInt* evalAPSInt(BinaryOperator::Opcode Op,
19049611Swpaul                                     const llvm::APSInt& V1,
19149611Swpaul                                     const llvm::APSInt& V2);
19249611Swpaul
19349611Swpaul  const std::pair<SVal, uintptr_t>&
19449611Swpaul  getPersistentSValWithData(const SVal& V, uintptr_t Data);
19549611Swpaul
19649611Swpaul  const std::pair<SVal, SVal>&
19749611Swpaul  getPersistentSValPair(const SVal& V1, const SVal& V2);
19849611Swpaul
19949611Swpaul  const SVal* getPersistentSVal(SVal X);
20049611Swpaul};
20149611Swpaul
20249611Swpaul} // end GR namespace
20350675Swpaul
20450675Swpaul} // end clang namespace
20550675Swpaul
20650675Swpaul#endif
20750675Swpaul