forked from OSchip/llvm-project
parent
fa9ae6739a
commit
b2c9aa6cbc
|
@ -0,0 +1,260 @@
|
|||
//=== AnalysisContext.h - Analysis context for Path Sens analysis --*- C++ -*-//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines AnalysisContext, a class that manages the analysis context
|
||||
// data for path sensitive analysis.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
|
||||
#define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
|
||||
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class Decl;
|
||||
class Stmt;
|
||||
class CFG;
|
||||
class CFGBlock;
|
||||
class LiveVariables;
|
||||
class ParentMap;
|
||||
class ImplicitParamDecl;
|
||||
class LocationContextManager;
|
||||
class StackFrameContext;
|
||||
|
||||
/// AnalysisContext contains the context data for the function or method under
|
||||
/// analysis.
|
||||
class AnalysisContext {
|
||||
const Decl *D;
|
||||
|
||||
// AnalysisContext owns the following data.
|
||||
CFG *cfg;
|
||||
LiveVariables *liveness;
|
||||
ParentMap *PM;
|
||||
llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
|
||||
llvm::BumpPtrAllocator A;
|
||||
bool AddEHEdges;
|
||||
public:
|
||||
AnalysisContext(const Decl *d, bool addehedges = false)
|
||||
: D(d), cfg(0), liveness(0), PM(0), ReferencedBlockVars(0),
|
||||
AddEHEdges(addehedges) {}
|
||||
|
||||
~AnalysisContext();
|
||||
|
||||
ASTContext &getASTContext() { return D->getASTContext(); }
|
||||
const Decl *getDecl() { return D; }
|
||||
/// getAddEHEdges - Return true iff we are adding exceptional edges from
|
||||
/// callExprs. If this is false, then try/catch statements and blocks
|
||||
/// reachable from them can appear to be dead in the CFG, analysis passes must
|
||||
/// cope with that.
|
||||
bool getAddEHEdges() const { return AddEHEdges; }
|
||||
Stmt *getBody();
|
||||
CFG *getCFG();
|
||||
ParentMap &getParentMap();
|
||||
LiveVariables *getLiveVariables();
|
||||
|
||||
typedef const VarDecl * const * referenced_decls_iterator;
|
||||
|
||||
std::pair<referenced_decls_iterator, referenced_decls_iterator>
|
||||
getReferencedBlockVars(const BlockDecl *BD);
|
||||
|
||||
/// Return the ImplicitParamDecl* associated with 'self' if this
|
||||
/// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
|
||||
const ImplicitParamDecl *getSelfDecl() const;
|
||||
};
|
||||
|
||||
class AnalysisContextManager {
|
||||
typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
|
||||
ContextMap Contexts;
|
||||
public:
|
||||
~AnalysisContextManager();
|
||||
|
||||
AnalysisContext *getContext(const Decl *D);
|
||||
|
||||
// Discard all previously created AnalysisContexts.
|
||||
void clear();
|
||||
};
|
||||
|
||||
class LocationContext : public llvm::FoldingSetNode {
|
||||
public:
|
||||
enum ContextKind { StackFrame, Scope, Block };
|
||||
|
||||
private:
|
||||
ContextKind Kind;
|
||||
AnalysisContext *Ctx;
|
||||
const LocationContext *Parent;
|
||||
|
||||
protected:
|
||||
LocationContext(ContextKind k, AnalysisContext *ctx,
|
||||
const LocationContext *parent)
|
||||
: Kind(k), Ctx(ctx), Parent(parent) {}
|
||||
|
||||
public:
|
||||
virtual ~LocationContext();
|
||||
|
||||
ContextKind getKind() const { return Kind; }
|
||||
|
||||
AnalysisContext *getAnalysisContext() const { return Ctx; }
|
||||
|
||||
const LocationContext *getParent() const { return Parent; }
|
||||
|
||||
const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
|
||||
|
||||
CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
|
||||
|
||||
LiveVariables *getLiveVariables() const {
|
||||
return getAnalysisContext()->getLiveVariables();
|
||||
}
|
||||
|
||||
ParentMap &getParentMap() const {
|
||||
return getAnalysisContext()->getParentMap();
|
||||
}
|
||||
|
||||
const ImplicitParamDecl *getSelfDecl() const {
|
||||
return Ctx->getSelfDecl();
|
||||
}
|
||||
|
||||
const StackFrameContext *getCurrentStackFrame() const;
|
||||
const StackFrameContext *
|
||||
getStackFrameForDeclContext(const DeclContext *DC) const;
|
||||
|
||||
virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
|
||||
|
||||
static bool classof(const LocationContext*) { return true; }
|
||||
|
||||
public:
|
||||
static void ProfileCommon(llvm::FoldingSetNodeID &ID,
|
||||
ContextKind ck,
|
||||
AnalysisContext *ctx,
|
||||
const LocationContext *parent,
|
||||
const void* data);
|
||||
};
|
||||
|
||||
class StackFrameContext : public LocationContext {
|
||||
// The callsite where this stack frame is established.
|
||||
const Stmt *CallSite;
|
||||
|
||||
// The parent block of the callsite.
|
||||
const CFGBlock *Block;
|
||||
|
||||
// The index of the callsite in the CFGBlock.
|
||||
unsigned Index;
|
||||
|
||||
friend class LocationContextManager;
|
||||
StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const Stmt *s, const CFGBlock *blk, unsigned idx)
|
||||
: LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
|
||||
Index(idx) {}
|
||||
|
||||
public:
|
||||
~StackFrameContext() {}
|
||||
|
||||
const Stmt *getCallSite() const { return CallSite; }
|
||||
|
||||
const CFGBlock *getCallSiteBlock() const { return Block; }
|
||||
|
||||
unsigned getIndex() const { return Index; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
|
||||
const LocationContext *parent, const Stmt *s,
|
||||
const CFGBlock *blk, unsigned idx) {
|
||||
ProfileCommon(ID, StackFrame, ctx, parent, s);
|
||||
ID.AddPointer(blk);
|
||||
ID.AddInteger(idx);
|
||||
}
|
||||
|
||||
static bool classof(const LocationContext* Ctx) {
|
||||
return Ctx->getKind() == StackFrame;
|
||||
}
|
||||
};
|
||||
|
||||
class ScopeContext : public LocationContext {
|
||||
const Stmt *Enter;
|
||||
|
||||
friend class LocationContextManager;
|
||||
ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const Stmt *s)
|
||||
: LocationContext(Scope, ctx, parent), Enter(s) {}
|
||||
|
||||
public:
|
||||
~ScopeContext() {}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
|
||||
const LocationContext *parent, const Stmt *s) {
|
||||
ProfileCommon(ID, Scope, ctx, parent, s);
|
||||
}
|
||||
|
||||
static bool classof(const LocationContext* Ctx) {
|
||||
return Ctx->getKind() == Scope;
|
||||
}
|
||||
};
|
||||
|
||||
class BlockInvocationContext : public LocationContext {
|
||||
// FIXME: Add back context-sensivity (we don't want libAnalysis to know
|
||||
// about MemRegion).
|
||||
const BlockDecl *BD;
|
||||
|
||||
friend class LocationContextManager;
|
||||
|
||||
BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const BlockDecl *bd)
|
||||
: LocationContext(Block, ctx, parent), BD(bd) {}
|
||||
|
||||
public:
|
||||
~BlockInvocationContext() {}
|
||||
|
||||
const BlockDecl *getBlockDecl() const { return BD; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
|
||||
const LocationContext *parent, const BlockDecl *bd) {
|
||||
ProfileCommon(ID, Block, ctx, parent, bd);
|
||||
}
|
||||
|
||||
static bool classof(const LocationContext* Ctx) {
|
||||
return Ctx->getKind() == Block;
|
||||
}
|
||||
};
|
||||
|
||||
class LocationContextManager {
|
||||
llvm::FoldingSet<LocationContext> Contexts;
|
||||
public:
|
||||
~LocationContextManager();
|
||||
|
||||
const StackFrameContext *getStackFrame(AnalysisContext *ctx,
|
||||
const LocationContext *parent,
|
||||
const Stmt *s, const CFGBlock *blk,
|
||||
unsigned idx);
|
||||
|
||||
const ScopeContext *getScope(AnalysisContext *ctx,
|
||||
const LocationContext *parent,
|
||||
const Stmt *s);
|
||||
|
||||
/// Discard all previously created LocationContext objects.
|
||||
void clear();
|
||||
private:
|
||||
template <typename LOC, typename DATA>
|
||||
const LOC *getLocationContext(AnalysisContext *ctx,
|
||||
const LocationContext *parent,
|
||||
const DATA *d);
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
#endif
|
Loading…
Reference in New Issue