forked from OSchip/llvm-project
139 lines
3.9 KiB
C++
139 lines
3.9 KiB
C++
//== AnalysisContext.cpp - 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.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/Analysis/PathSensitive/AnalysisContext.h"
|
|
#include "clang/Analysis/Analyses/LiveVariables.h"
|
|
#include "clang/Analysis/CFG.h"
|
|
#include "clang/AST/Decl.h"
|
|
#include "clang/AST/DeclObjC.h"
|
|
#include "clang/AST/ParentMap.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
using namespace clang;
|
|
|
|
AnalysisContext::~AnalysisContext() {
|
|
delete cfg;
|
|
delete liveness;
|
|
delete PM;
|
|
}
|
|
|
|
AnalysisContextManager::~AnalysisContextManager() {
|
|
for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
|
|
delete I->second;
|
|
}
|
|
|
|
Stmt *AnalysisContext::getBody() {
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
|
|
return FD->getBody();
|
|
else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
|
|
return MD->getBody();
|
|
|
|
llvm::llvm_unreachable("unknown code decl");
|
|
}
|
|
|
|
const ImplicitParamDecl *AnalysisContext::getSelfDecl() const {
|
|
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
|
|
return MD->getSelfDecl();
|
|
|
|
return NULL;
|
|
}
|
|
|
|
CFG *AnalysisContext::getCFG() {
|
|
if (!cfg)
|
|
cfg = CFG::buildCFG(getBody(), &D->getASTContext());
|
|
return cfg;
|
|
}
|
|
|
|
ParentMap &AnalysisContext::getParentMap() {
|
|
if (!PM)
|
|
PM = new ParentMap(getBody());
|
|
return *PM;
|
|
}
|
|
|
|
LiveVariables *AnalysisContext::getLiveVariables() {
|
|
if (!liveness) {
|
|
CFG *c = getCFG();
|
|
if (!c)
|
|
return 0;
|
|
|
|
liveness = new LiveVariables(D->getASTContext(), *c);
|
|
liveness->runOnCFG(*c);
|
|
liveness->runOnAllBlocks(*c, 0, true);
|
|
}
|
|
|
|
return liveness;
|
|
}
|
|
|
|
AnalysisContext *AnalysisContextManager::getContext(const Decl *D) {
|
|
AnalysisContext *&AC = Contexts[D];
|
|
if (!AC)
|
|
AC = new AnalysisContext(D);
|
|
|
|
return AC;
|
|
}
|
|
|
|
void LocationContext::Profile(llvm::FoldingSetNodeID &ID, ContextKind k,
|
|
AnalysisContext *ctx,
|
|
const LocationContext *parent) {
|
|
ID.AddInteger(k);
|
|
ID.AddPointer(ctx);
|
|
ID.AddPointer(parent);
|
|
}
|
|
|
|
void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID,AnalysisContext *ctx,
|
|
const LocationContext *parent, const Stmt *s) {
|
|
LocationContext::Profile(ID, StackFrame, ctx, parent);
|
|
ID.AddPointer(s);
|
|
}
|
|
|
|
void ScopeContext::Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
|
|
const LocationContext *parent, const Stmt *s) {
|
|
LocationContext::Profile(ID, Scope, ctx, parent);
|
|
ID.AddPointer(s);
|
|
}
|
|
|
|
StackFrameContext*
|
|
LocationContextManager::getStackFrame(AnalysisContext *ctx,
|
|
const LocationContext *parent,
|
|
const Stmt *s) {
|
|
llvm::FoldingSetNodeID ID;
|
|
StackFrameContext::Profile(ID, ctx, parent, s);
|
|
void *InsertPos;
|
|
|
|
StackFrameContext *f =
|
|
cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
|
|
if (!f) {
|
|
f = new StackFrameContext(ctx, parent, s);
|
|
Contexts.InsertNode(f, InsertPos);
|
|
}
|
|
return f;
|
|
}
|
|
|
|
ScopeContext *LocationContextManager::getScope(AnalysisContext *ctx,
|
|
const LocationContext *parent,
|
|
const Stmt *s) {
|
|
llvm::FoldingSetNodeID ID;
|
|
ScopeContext::Profile(ID, ctx, parent, s);
|
|
void *InsertPos;
|
|
|
|
ScopeContext *scope =
|
|
cast_or_null<ScopeContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
|
|
|
|
if (!scope) {
|
|
scope = new ScopeContext(ctx, parent, s);
|
|
Contexts.InsertNode(scope, InsertPos);
|
|
}
|
|
return scope;
|
|
}
|