Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //==- BasicValueFactory.h - Basic values for Path Sens analysis --*- C++ -*-==//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. //  This file defines BasicValueFactory, a class that manages the lifetime
  10. //  of APSInt objects and symbolic constraints used by ExprEngine
  11. //  and related classes.
  12. //
  13. //===----------------------------------------------------------------------===//
  14.  
  15. #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BASICVALUEFACTORY_H
  16. #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BASICVALUEFACTORY_H
  17.  
  18. #include "clang/AST/ASTContext.h"
  19. #include "clang/AST/Expr.h"
  20. #include "clang/AST/Type.h"
  21. #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
  22. #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
  23. #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
  24. #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
  25. #include "llvm/ADT/APSInt.h"
  26. #include "llvm/ADT/FoldingSet.h"
  27. #include "llvm/ADT/ImmutableList.h"
  28. #include "llvm/ADT/iterator_range.h"
  29. #include "llvm/Support/Allocator.h"
  30. #include <cassert>
  31. #include <cstdint>
  32. #include <utility>
  33.  
  34. namespace clang {
  35.  
  36. class CXXBaseSpecifier;
  37.  
  38. namespace ento {
  39.  
  40. class CompoundValData : public llvm::FoldingSetNode {
  41.   QualType T;
  42.   llvm::ImmutableList<SVal> L;
  43.  
  44. public:
  45.   CompoundValData(QualType t, llvm::ImmutableList<SVal> l) : T(t), L(l) {
  46.     assert(NonLoc::isCompoundType(t));
  47.   }
  48.  
  49.   using iterator = llvm::ImmutableList<SVal>::iterator;
  50.  
  51.   iterator begin() const { return L.begin(); }
  52.   iterator end() const { return L.end(); }
  53.  
  54.   QualType getType() const { return T; }
  55.  
  56.   static void Profile(llvm::FoldingSetNodeID& ID, QualType T,
  57.                       llvm::ImmutableList<SVal> L);
  58.  
  59.   void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, T, L); }
  60. };
  61.  
  62. class LazyCompoundValData : public llvm::FoldingSetNode {
  63.   StoreRef store;
  64.   const TypedValueRegion *region;
  65.  
  66. public:
  67.   LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r)
  68.       : store(st), region(r) {
  69.     assert(r);
  70.     assert(NonLoc::isCompoundType(r->getValueType()));
  71.   }
  72.  
  73.   /// It might return null.
  74.   const void *getStore() const { return store.getStore(); }
  75.  
  76.   LLVM_ATTRIBUTE_RETURNS_NONNULL
  77.   const TypedValueRegion *getRegion() const { return region; }
  78.  
  79.   static void Profile(llvm::FoldingSetNodeID& ID,
  80.                       const StoreRef &store,
  81.                       const TypedValueRegion *region);
  82.  
  83.   void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); }
  84. };
  85.  
  86. class PointerToMemberData : public llvm::FoldingSetNode {
  87.   const NamedDecl *D;
  88.   llvm::ImmutableList<const CXXBaseSpecifier *> L;
  89.  
  90. public:
  91.   PointerToMemberData(const NamedDecl *D,
  92.                       llvm::ImmutableList<const CXXBaseSpecifier *> L)
  93.       : D(D), L(L) {}
  94.  
  95.   using iterator = llvm::ImmutableList<const CXXBaseSpecifier *>::iterator;
  96.  
  97.   iterator begin() const { return L.begin(); }
  98.   iterator end() const { return L.end(); }
  99.  
  100.   static void Profile(llvm::FoldingSetNodeID &ID, const NamedDecl *D,
  101.                       llvm::ImmutableList<const CXXBaseSpecifier *> L);
  102.  
  103.   void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, D, L); }
  104.  
  105.   /// It might return null.
  106.   const NamedDecl *getDeclaratorDecl() const { return D; }
  107.  
  108.   llvm::ImmutableList<const CXXBaseSpecifier *> getCXXBaseList() const {
  109.     return L;
  110.   }
  111. };
  112.  
  113. class BasicValueFactory {
  114.   using APSIntSetTy =
  115.       llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt>>;
  116.  
  117.   ASTContext &Ctx;
  118.   llvm::BumpPtrAllocator& BPAlloc;
  119.  
  120.   APSIntSetTy APSIntSet;
  121.   void *PersistentSVals = nullptr;
  122.   void *PersistentSValPairs = nullptr;
  123.  
  124.   llvm::ImmutableList<SVal>::Factory SValListFactory;
  125.   llvm::ImmutableList<const CXXBaseSpecifier *>::Factory CXXBaseListFactory;
  126.   llvm::FoldingSet<CompoundValData>  CompoundValDataSet;
  127.   llvm::FoldingSet<LazyCompoundValData> LazyCompoundValDataSet;
  128.   llvm::FoldingSet<PointerToMemberData> PointerToMemberDataSet;
  129.  
  130.   // This is private because external clients should use the factory
  131.   // method that takes a QualType.
  132.   const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
  133.  
  134. public:
  135.   BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator &Alloc)
  136.       : Ctx(ctx), BPAlloc(Alloc), SValListFactory(Alloc),
  137.         CXXBaseListFactory(Alloc) {}
  138.  
  139.   ~BasicValueFactory();
  140.  
  141.   ASTContext &getContext() const { return Ctx; }
  142.  
  143.   const llvm::APSInt& getValue(const llvm::APSInt& X);
  144.   const llvm::APSInt& getValue(const llvm::APInt& X, bool isUnsigned);
  145.   const llvm::APSInt& getValue(uint64_t X, QualType T);
  146.  
  147.   /// Returns the type of the APSInt used to store values of the given QualType.
  148.   APSIntType getAPSIntType(QualType T) const {
  149.     // For the purposes of the analysis and constraints, we treat atomics
  150.     // as their underlying types.
  151.     if (const AtomicType *AT = T->getAs<AtomicType>()) {
  152.       T = AT->getValueType();
  153.     }
  154.  
  155.     if (T->isIntegralOrEnumerationType() || Loc::isLocType(T)) {
  156.       return APSIntType(Ctx.getIntWidth(T),
  157.                         !T->isSignedIntegerOrEnumerationType());
  158.     } else {
  159.       // implicitly handle case of T->isFixedPointType()
  160.       return APSIntType(Ctx.getIntWidth(T), T->isUnsignedFixedPointType());
  161.     }
  162.  
  163.     llvm_unreachable("Unsupported type in getAPSIntType!");
  164.   }
  165.  
  166.   /// Convert - Create a new persistent APSInt with the same value as 'From'
  167.   ///  but with the bitwidth and signedness of 'To'.
  168.   const llvm::APSInt &Convert(const llvm::APSInt& To,
  169.                               const llvm::APSInt& From) {
  170.     APSIntType TargetType(To);
  171.     if (TargetType == APSIntType(From))
  172.       return From;
  173.  
  174.     return getValue(TargetType.convert(From));
  175.   }
  176.  
  177.   const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {
  178.     APSIntType TargetType = getAPSIntType(T);
  179.     return Convert(TargetType, From);
  180.   }
  181.  
  182.   const llvm::APSInt &Convert(APSIntType TargetType, const llvm::APSInt &From) {
  183.     if (TargetType == APSIntType(From))
  184.       return From;
  185.  
  186.     return getValue(TargetType.convert(From));
  187.   }
  188.  
  189.   const llvm::APSInt &getIntValue(uint64_t X, bool isUnsigned) {
  190.     QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy;
  191.     return getValue(X, T);
  192.   }
  193.  
  194.   const llvm::APSInt &getMaxValue(const llvm::APSInt &v) {
  195.     return getValue(APSIntType(v).getMaxValue());
  196.   }
  197.  
  198.   const llvm::APSInt &getMinValue(const llvm::APSInt &v) {
  199.     return getValue(APSIntType(v).getMinValue());
  200.   }
  201.  
  202.   const llvm::APSInt &getMaxValue(QualType T) {
  203.     return getMaxValue(getAPSIntType(T));
  204.   }
  205.  
  206.   const llvm::APSInt &getMinValue(QualType T) {
  207.     return getMinValue(getAPSIntType(T));
  208.   }
  209.  
  210.   const llvm::APSInt &getMaxValue(APSIntType T) {
  211.     return getValue(T.getMaxValue());
  212.   }
  213.  
  214.   const llvm::APSInt &getMinValue(APSIntType T) {
  215.     return getValue(T.getMinValue());
  216.   }
  217.  
  218.   const llvm::APSInt &Add1(const llvm::APSInt &V) {
  219.     llvm::APSInt X = V;
  220.     ++X;
  221.     return getValue(X);
  222.   }
  223.  
  224.   const llvm::APSInt &Sub1(const llvm::APSInt &V) {
  225.     llvm::APSInt X = V;
  226.     --X;
  227.     return getValue(X);
  228.   }
  229.  
  230.   const llvm::APSInt &getZeroWithTypeSize(QualType T) {
  231.     assert(T->isScalarType());
  232.     return getValue(0, Ctx.getTypeSize(T), true);
  233.   }
  234.  
  235.   const llvm::APSInt &getTruthValue(bool b, QualType T) {
  236.     return getValue(b ? 1 : 0, Ctx.getIntWidth(T),
  237.                     T->isUnsignedIntegerOrEnumerationType());
  238.   }
  239.  
  240.   const llvm::APSInt &getTruthValue(bool b) {
  241.     return getTruthValue(b, Ctx.getLogicalOperationType());
  242.   }
  243.  
  244.   const CompoundValData *getCompoundValData(QualType T,
  245.                                             llvm::ImmutableList<SVal> Vals);
  246.  
  247.   const LazyCompoundValData *getLazyCompoundValData(const StoreRef &store,
  248.                                             const TypedValueRegion *region);
  249.  
  250.   const PointerToMemberData *
  251.   getPointerToMemberData(const NamedDecl *ND,
  252.                          llvm::ImmutableList<const CXXBaseSpecifier *> L);
  253.  
  254.   llvm::ImmutableList<SVal> getEmptySValList() {
  255.     return SValListFactory.getEmptyList();
  256.   }
  257.  
  258.   llvm::ImmutableList<SVal> prependSVal(SVal X, llvm::ImmutableList<SVal> L) {
  259.     return SValListFactory.add(X, L);
  260.   }
  261.  
  262.   llvm::ImmutableList<const CXXBaseSpecifier *> getEmptyCXXBaseList() {
  263.     return CXXBaseListFactory.getEmptyList();
  264.   }
  265.  
  266.   llvm::ImmutableList<const CXXBaseSpecifier *> prependCXXBase(
  267.       const CXXBaseSpecifier *CBS,
  268.       llvm::ImmutableList<const CXXBaseSpecifier *> L) {
  269.     return CXXBaseListFactory.add(CBS, L);
  270.   }
  271.  
  272.   const PointerToMemberData *
  273.   accumCXXBase(llvm::iterator_range<CastExpr::path_const_iterator> PathRange,
  274.                const nonloc::PointerToMember &PTM, const clang::CastKind &kind);
  275.  
  276.   const llvm::APSInt* evalAPSInt(BinaryOperator::Opcode Op,
  277.                                      const llvm::APSInt& V1,
  278.                                      const llvm::APSInt& V2);
  279.  
  280.   const std::pair<SVal, uintptr_t>&
  281.   getPersistentSValWithData(const SVal& V, uintptr_t Data);
  282.  
  283.   const std::pair<SVal, SVal>&
  284.   getPersistentSValPair(const SVal& V1, const SVal& V2);
  285.  
  286.   const SVal* getPersistentSVal(SVal X);
  287. };
  288.  
  289. } // namespace ento
  290.  
  291. } // namespace clang
  292.  
  293. #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BASICVALUEFACTORY_H
  294.