//===-- GRConstants.cpp - Simple, Path-Sens. Constant Prop. ------*- C++ -*-==// // // The LLValM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Constant Propagation via Graph Reachability // // This files defines a simple analysis that performs path-sensitive // constant propagation within a function. An example use of this analysis // is to perform simple checks for NULL dereferences. // //===----------------------------------------------------------------------===// #include "clang/Analysis/PathSensitive/GREngine.h" #include "clang/AST/Expr.h" #include "clang/AST/ASTContext.h" #include "clang/Analysis/Analyses/LiveVariables.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Streams.h" #include #ifndef NDEBUG #include "llvm/Support/GraphWriter.h" #include #endif using namespace clang; using llvm::dyn_cast; using llvm::cast; using llvm::APSInt; //===----------------------------------------------------------------------===// /// ValueKey - A variant smart pointer that wraps either a ValueDecl* or a /// Stmt*. Use cast<> or dyn_cast<> to get actual pointer type //===----------------------------------------------------------------------===// namespace { class VISIBILITY_HIDDEN ValueKey { uintptr_t Raw; void operator=(const ValueKey& RHS); // Do not implement. public: enum Kind { IsSubExpr=0x0, IsBlkExpr=0x1, IsDecl=0x2, Flags=0x3 }; inline void* getPtr() const { return reinterpret_cast(Raw & ~Flags); } inline Kind getKind() const { return (Kind) (Raw & Flags); } ValueKey(const ValueDecl* VD) : Raw(reinterpret_cast(VD) | IsDecl) { assert(VD); } ValueKey(Stmt* S, bool isBlkExpr = false) : Raw(reinterpret_cast(S) | (isBlkExpr ? IsBlkExpr : IsSubExpr)){ assert(S); } bool isSubExpr() const { return getKind() == IsSubExpr; } bool isDecl() const { return getKind() == IsDecl; } inline void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddPointer(getPtr()); } inline bool operator==(const ValueKey& X) const { return getPtr() == X.getPtr(); } inline bool operator!=(const ValueKey& X) const { return !operator==(X); } inline bool operator<(const ValueKey& X) const { Kind k = getKind(), Xk = X.getKind(); if (k == IsDecl) { if (Xk != IsDecl) return false; } else { if (Xk == IsDecl) return true; } return getPtr() < X.getPtr(); } }; } // end anonymous namespace // Machinery to get cast<> and dyn_cast<> working with ValueKey. namespace llvm { template<> inline bool isa(const ValueKey& V) { return V.getKind() == ValueKey::IsDecl; } template<> inline bool isa(const ValueKey& V) { return ((unsigned) V.getKind()) != ValueKey::IsDecl; } template<> struct VISIBILITY_HIDDEN cast_retty_impl { typedef const ValueDecl* ret_type; }; template<> struct VISIBILITY_HIDDEN cast_retty_impl { typedef const Stmt* ret_type; }; template<> struct VISIBILITY_HIDDEN simplify_type { typedef void* SimpleType; static inline SimpleType getSimplifiedValue(const ValueKey &V) { return V.getPtr(); } }; } // end llvm namespace //===----------------------------------------------------------------------===// // ValueManager. //===----------------------------------------------------------------------===// namespace { typedef llvm::ImmutableSet APSIntSetTy; class VISIBILITY_HIDDEN ValueManager { APSIntSetTy::Factory APSIntSetFactory; ASTContext* Ctx; public: ValueManager() {} ~ValueManager() {} void setContext(ASTContext* ctx) { Ctx = ctx; } ASTContext* getContext() const { return Ctx; } APSIntSetTy GetEmptyAPSIntSet() { return APSIntSetFactory.GetEmptySet(); } APSIntSetTy AddToSet(const APSIntSetTy& Set, const APSInt& Val) { return APSIntSetFactory.Add(Set, Val); } }; } // end anonymous namespace template