Newer
Older
//===-- GRConstants.cpp - Simple, Path-Sens. Constant Prop. ------*- C++ -*-==//
//
Ted Kremenek
committed
// 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"
Ted Kremenek
committed
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
Ted Kremenek
committed
#include "llvm/Support/Streams.h"
#ifndef NDEBUG
#include "llvm/Support/GraphWriter.h"
#include <sstream>
#endif
using namespace clang;
using llvm::dyn_cast;
using llvm::cast;
//===----------------------------------------------------------------------===//
Ted Kremenek
committed
/// ValueKey - A variant smart pointer that wraps either a ValueDecl* or a
/// Stmt*. Use cast<> or dyn_cast<> to get actual pointer type
//===----------------------------------------------------------------------===//
namespace {
Ted Kremenek
committed
class VISIBILITY_HIDDEN ValueKey {
public:
enum Kind { IsSubExp=0x0, IsBlkExpr=0x1, IsDecl=0x2, Flags=0x3 };
inline void* getPtr() const { return reinterpret_cast<void*>(Raw & ~Flags); }
Ted Kremenek
committed
inline Kind getKind() const { return (Kind) (Raw & Flags); }
Ted Kremenek
committed
ValueKey(const ValueDecl* VD)
: Raw(reinterpret_cast<uintptr_t>(VD) | IsDecl) {}
ValueKey(Stmt* S, bool isBlkExpr = false)
Ted Kremenek
committed
: Raw(reinterpret_cast<uintptr_t>(S) | (isBlkExpr ? IsBlkExpr : IsSubExp)){}
bool isSubExpr() const { return getKind() == IsSubExp; }
Ted Kremenek
committed
bool isDecl() const { return getKind() == IsDecl; }
inline void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddPointer(getPtr());
ID.AddInteger((unsigned) getKind());
Ted Kremenek
committed
}
inline bool operator==(const ValueKey& X) const {
return getPtr() == X.getPtr();
Ted Kremenek
committed
}
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;
}
Ted Kremenek
committed
return getPtr() < X.getPtr();
};
} // end anonymous namespace
Ted Kremenek
committed
// Machinery to get cast<> and dyn_cast<> working with ValueKey.
namespace llvm {
Ted Kremenek
committed
template<> inline bool isa<ValueDecl,ValueKey>(const ValueKey& V) {
return V.getKind() == ValueKey::IsDecl;
Ted Kremenek
committed
template<> inline bool isa<Stmt,ValueKey>(const ValueKey& V) {
return ((unsigned) V.getKind()) != ValueKey::IsDecl;
Ted Kremenek
committed
template<> struct VISIBILITY_HIDDEN cast_retty_impl<ValueDecl,ValueKey> {
typedef const ValueDecl* ret_type;
Ted Kremenek
committed
template<> struct VISIBILITY_HIDDEN cast_retty_impl<Stmt,ValueKey> {
typedef const Stmt* ret_type;
};
Ted Kremenek
committed
template<> struct VISIBILITY_HIDDEN simplify_type<ValueKey> {
typedef void* SimpleType;
Ted Kremenek
committed
static inline SimpleType getSimplifiedValue(const ValueKey &V) {
return V.getPtr();
}
};
} // end llvm namespace
//===----------------------------------------------------------------------===//
Ted Kremenek
committed
// ValueManager.
//===----------------------------------------------------------------------===//
Ted Kremenek
committed
namespace {
typedef llvm::ImmutableSet<llvm::APSInt > APSIntSetTy;
class VISIBILITY_HIDDEN ValueManager {
APSIntSetTy::Factory APSIntSetFactory;
ASTContext* Ctx;
Ted Kremenek
committed
public:
ValueManager() {}
~ValueManager() {}
void setContext(ASTContext* ctx) { Ctx = ctx; }
ASTContext* getContext() const { return Ctx; }
Ted Kremenek
committed
APSIntSetTy GetEmptyAPSIntSet() {
return APSIntSetFactory.GetEmptySet();
}
APSIntSetTy AddToSet(const APSIntSetTy& Set, const llvm::APSInt& Val) {
return APSIntSetFactory.Add(Set, Val);
}
};
} // end anonymous namespace
Ted Kremenek
committed
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
//===----------------------------------------------------------------------===//
// Expression Values.
//===----------------------------------------------------------------------===//
namespace {
class VISIBILITY_HIDDEN ExprValue {
public:
enum Kind { // L-Values.
LValueDeclKind = 0x0,
// Special "Invalid" value.
InvalidValueKind = 0x1,
// R-Values.
RValueMayEqualSetKind = 0x2,
// Note that the Lvalue and RValue "kinds" overlap;
// the "InvalidValue" class can be used either as
// an LValue or RValue.
MinLValueKind = 0x0, MaxLValueKind = 0x1,
MinRValueKind = 0x1, MaxRValueKind = 0x2 };
private:
enum Kind kind;
void* Data;
protected:
ExprValue(Kind k, void* d) : kind(k), Data(d) {}
void* getRawPtr() const { return Data; }
public:
~ExprValue() {};
ExprValue EvalCast(ValueManager& ValMgr, Expr* CastExpr) const;
Ted Kremenek
committed
void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned) getKind());
ID.AddPointer(Data);
}
bool operator==(const ExprValue& RHS) const {
return kind == RHS.kind && Data == RHS.Data;
Ted Kremenek
committed
Kind getKind() const { return kind; }
bool isValid() const { return getKind() != InvalidValueKind; }
void print(std::ostream& OS) const;
void print() const { print(*llvm::cerr.stream()); }
// Implement isa<T> support.
static inline bool classof(const ExprValue*) { return true; }
};
class VISIBILITY_HIDDEN InvalidValue : public ExprValue {
public:
Loading
Loading full blame...