forked from OSchip/llvm-project
Rework interaction between AnalysisContext and CFG::BuildOptions to keep a BuildOptions object around instead of keeping a copy of the flags.
Moreover, change AnalysisContext to use an OwningPtr for created analysis objects instead of directly managing them. Finally, add a 'forcedBlkExprs' entry to CFG::BuildOptions that will be used by the CFGBuilder to force specific expressions to be block-level expressions. llvm-svn: 127385
This commit is contained in:
parent
241bdc0de7
commit
f9d8290af1
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/Analysis/CFG.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
|
@ -27,8 +28,6 @@ namespace clang {
|
|||
|
||||
class Decl;
|
||||
class Stmt;
|
||||
class CFG;
|
||||
class CFGBlock;
|
||||
class CFGReachabilityAnalysis;
|
||||
class CFGStmtMap;
|
||||
class LiveVariables;
|
||||
|
@ -48,33 +47,32 @@ class AnalysisContext {
|
|||
// TranslationUnit is NULL if we don't have multiple translation units.
|
||||
idx::TranslationUnit *TU;
|
||||
|
||||
// AnalysisContext owns the following data.
|
||||
CFG *cfg, *completeCFG;
|
||||
CFGStmtMap *cfgStmtMap;
|
||||
llvm::OwningPtr<CFG> cfg, completeCFG;
|
||||
llvm::OwningPtr<CFGStmtMap> cfgStmtMap;
|
||||
|
||||
CFG::BuildOptions cfgBuildOptions;
|
||||
CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
|
||||
|
||||
bool builtCFG, builtCompleteCFG;
|
||||
LiveVariables *liveness;
|
||||
LiveVariables *relaxedLiveness;
|
||||
ParentMap *PM;
|
||||
PseudoConstantAnalysis *PCA;
|
||||
CFGReachabilityAnalysis *CFA;
|
||||
llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
|
||||
const bool useUnoptimizedCFG;
|
||||
|
||||
llvm::OwningPtr<LiveVariables> liveness;
|
||||
llvm::OwningPtr<LiveVariables> relaxedLiveness;
|
||||
llvm::OwningPtr<ParentMap> PM;
|
||||
llvm::OwningPtr<PseudoConstantAnalysis> PCA;
|
||||
llvm::OwningPtr<CFGReachabilityAnalysis> CFA;
|
||||
|
||||
llvm::BumpPtrAllocator A;
|
||||
bool UseUnoptimizedCFG;
|
||||
bool AddEHEdges;
|
||||
bool AddImplicitDtors;
|
||||
bool AddInitializers;
|
||||
|
||||
// FIXME: remove.
|
||||
llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
|
||||
|
||||
public:
|
||||
AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
|
||||
bool useUnoptimizedCFG = false,
|
||||
bool addehedges = false,
|
||||
bool addImplicitDtors = false,
|
||||
bool addInitializers = false)
|
||||
: D(d), TU(tu), cfg(0), completeCFG(0), cfgStmtMap(0),
|
||||
builtCFG(false), builtCompleteCFG(false),
|
||||
liveness(0), relaxedLiveness(0), PM(0), PCA(0), CFA(0),
|
||||
ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
|
||||
AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors),
|
||||
AddInitializers(addInitializers) {}
|
||||
bool addInitializers = false);
|
||||
|
||||
~AnalysisContext();
|
||||
|
||||
|
@ -87,11 +85,12 @@ public:
|
|||
/// 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; }
|
||||
|
||||
bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
|
||||
bool getAddImplicitDtors() const { return AddImplicitDtors; }
|
||||
bool getAddInitializers() const { return AddInitializers; }
|
||||
bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
|
||||
bool getUseUnoptimizedCFG() const {
|
||||
return cfgBuildOptions.PruneTriviallyFalseEdges;
|
||||
}
|
||||
bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
|
||||
bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
|
||||
|
||||
Stmt *getBody();
|
||||
CFG *getCFG();
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "clang/Analysis/Support/BumpVector.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include <cassert>
|
||||
|
@ -532,13 +534,16 @@ public:
|
|||
|
||||
class BuildOptions {
|
||||
public:
|
||||
typedef llvm::DenseMap<const Stmt *, const CFGBlock> ForcedBlkExprs;
|
||||
ForcedBlkExprs **forcedBlkExprs;
|
||||
|
||||
bool PruneTriviallyFalseEdges:1;
|
||||
bool AddEHEdges:1;
|
||||
bool AddInitializers:1;
|
||||
bool AddImplicitDtors:1;
|
||||
|
||||
BuildOptions()
|
||||
: PruneTriviallyFalseEdges(true)
|
||||
: forcedBlkExprs(0), PruneTriviallyFalseEdges(true)
|
||||
, AddEHEdges(false)
|
||||
, AddInitializers(false)
|
||||
, AddImplicitDtors(false) {}
|
||||
|
@ -547,7 +552,7 @@ public:
|
|||
/// buildCFG - Builds a CFG from an AST. The responsibility to free the
|
||||
/// constructed CFG belongs to the caller.
|
||||
static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C,
|
||||
BuildOptions BO = BuildOptions());
|
||||
const BuildOptions &BO);
|
||||
|
||||
/// createBlock - Create a new block in the CFG. The CFG owns the block;
|
||||
/// the caller should not directly free it.
|
||||
|
|
|
@ -29,6 +29,24 @@
|
|||
|
||||
using namespace clang;
|
||||
|
||||
AnalysisContext::AnalysisContext(const Decl *d,
|
||||
idx::TranslationUnit *tu,
|
||||
bool useUnoptimizedCFG,
|
||||
bool addehedges,
|
||||
bool addImplicitDtors,
|
||||
bool addInitializers)
|
||||
: D(d), TU(tu),
|
||||
forcedBlkExprs(0),
|
||||
builtCFG(false), builtCompleteCFG(false),
|
||||
useUnoptimizedCFG(useUnoptimizedCFG),
|
||||
ReferencedBlockVars(0)
|
||||
{
|
||||
cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
|
||||
cfgBuildOptions.AddEHEdges = addehedges;
|
||||
cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
|
||||
cfgBuildOptions.AddInitializers = addInitializers;
|
||||
}
|
||||
|
||||
void AnalysisContextManager::clear() {
|
||||
for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
|
||||
delete I->second;
|
||||
|
@ -57,44 +75,38 @@ const ImplicitParamDecl *AnalysisContext::getSelfDecl() const {
|
|||
}
|
||||
|
||||
CFG *AnalysisContext::getCFG() {
|
||||
if (UseUnoptimizedCFG)
|
||||
if (useUnoptimizedCFG)
|
||||
return getUnoptimizedCFG();
|
||||
|
||||
if (!builtCFG) {
|
||||
CFG::BuildOptions B;
|
||||
B.AddEHEdges = AddEHEdges;
|
||||
B.AddImplicitDtors = AddImplicitDtors;
|
||||
B.AddInitializers = AddInitializers;
|
||||
cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), B);
|
||||
cfg.reset(CFG::buildCFG(D, getBody(),
|
||||
&D->getASTContext(), cfgBuildOptions));
|
||||
// Even when the cfg is not successfully built, we don't
|
||||
// want to try building it again.
|
||||
builtCFG = true;
|
||||
}
|
||||
return cfg;
|
||||
return cfg.get();
|
||||
}
|
||||
|
||||
CFG *AnalysisContext::getUnoptimizedCFG() {
|
||||
if (!builtCompleteCFG) {
|
||||
CFG::BuildOptions B;
|
||||
CFG::BuildOptions B = cfgBuildOptions;
|
||||
B.PruneTriviallyFalseEdges = false;
|
||||
B.AddEHEdges = AddEHEdges;
|
||||
B.AddImplicitDtors = AddImplicitDtors;
|
||||
B.AddInitializers = AddInitializers;
|
||||
completeCFG = CFG::buildCFG(D, getBody(), &D->getASTContext(), B);
|
||||
completeCFG.reset(CFG::buildCFG(D, getBody(), &D->getASTContext(), B));
|
||||
// Even when the cfg is not successfully built, we don't
|
||||
// want to try building it again.
|
||||
builtCompleteCFG = true;
|
||||
}
|
||||
return completeCFG;
|
||||
return completeCFG.get();
|
||||
}
|
||||
|
||||
CFGStmtMap *AnalysisContext::getCFGStmtMap() {
|
||||
if (cfgStmtMap)
|
||||
return cfgStmtMap;
|
||||
return cfgStmtMap.get();
|
||||
|
||||
if (CFG *c = getCFG()) {
|
||||
cfgStmtMap = CFGStmtMap::Build(c, &getParentMap());
|
||||
return cfgStmtMap;
|
||||
cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap()));
|
||||
return cfgStmtMap.get();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -102,11 +114,11 @@ CFGStmtMap *AnalysisContext::getCFGStmtMap() {
|
|||
|
||||
CFGReachabilityAnalysis *AnalysisContext::getCFGReachablityAnalysis() {
|
||||
if (CFA)
|
||||
return CFA;
|
||||
return CFA.get();
|
||||
|
||||
if (CFG *c = getCFG()) {
|
||||
CFA = new CFGReachabilityAnalysis(*c);
|
||||
return CFA;
|
||||
CFA.reset(new CFGReachabilityAnalysis(*c));
|
||||
return CFA.get();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -118,42 +130,37 @@ void AnalysisContext::dumpCFG() {
|
|||
|
||||
ParentMap &AnalysisContext::getParentMap() {
|
||||
if (!PM)
|
||||
PM = new ParentMap(getBody());
|
||||
PM.reset(new ParentMap(getBody()));
|
||||
return *PM;
|
||||
}
|
||||
|
||||
PseudoConstantAnalysis *AnalysisContext::getPseudoConstantAnalysis() {
|
||||
if (!PCA)
|
||||
PCA = new PseudoConstantAnalysis(getBody());
|
||||
return PCA;
|
||||
PCA.reset(new PseudoConstantAnalysis(getBody()));
|
||||
return PCA.get();
|
||||
}
|
||||
|
||||
LiveVariables *AnalysisContext::getLiveVariables() {
|
||||
if (!liveness) {
|
||||
CFG *c = getCFG();
|
||||
if (!c)
|
||||
return 0;
|
||||
|
||||
liveness = new LiveVariables(*this);
|
||||
liveness->runOnCFG(*c);
|
||||
liveness->runOnAllBlocks(*c, 0, true);
|
||||
if (CFG *c = getCFG()) {
|
||||
liveness.reset(new LiveVariables(*this));
|
||||
liveness->runOnCFG(*c);
|
||||
liveness->runOnAllBlocks(*c, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
return liveness;
|
||||
return liveness.get();
|
||||
}
|
||||
|
||||
LiveVariables *AnalysisContext::getRelaxedLiveVariables() {
|
||||
if (!relaxedLiveness) {
|
||||
CFG *c = getCFG();
|
||||
if (!c)
|
||||
return 0;
|
||||
if (!relaxedLiveness)
|
||||
if (CFG *c = getCFG()) {
|
||||
relaxedLiveness.reset(new LiveVariables(*this, false));
|
||||
relaxedLiveness->runOnCFG(*c);
|
||||
relaxedLiveness->runOnAllBlocks(*c, 0, true);
|
||||
}
|
||||
|
||||
relaxedLiveness = new LiveVariables(*this, false);
|
||||
relaxedLiveness->runOnCFG(*c);
|
||||
relaxedLiveness->runOnAllBlocks(*c, 0, true);
|
||||
}
|
||||
|
||||
return relaxedLiveness;
|
||||
return relaxedLiveness.get();
|
||||
}
|
||||
|
||||
AnalysisContext *AnalysisContextManager::getContext(const Decl *D,
|
||||
|
@ -370,14 +377,7 @@ AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) {
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
AnalysisContext::~AnalysisContext() {
|
||||
delete cfg;
|
||||
delete completeCFG;
|
||||
delete cfgStmtMap;
|
||||
delete liveness;
|
||||
delete relaxedLiveness;
|
||||
delete PM;
|
||||
delete PCA;
|
||||
delete CFA;
|
||||
delete forcedBlkExprs;
|
||||
delete ReferencedBlockVars;
|
||||
}
|
||||
|
||||
|
|
|
@ -275,22 +275,23 @@ class CFGBuilder {
|
|||
LabelSetTy AddressTakenLabels;
|
||||
|
||||
bool badCFG;
|
||||
CFG::BuildOptions BuildOpts;
|
||||
const CFG::BuildOptions &BuildOpts;
|
||||
|
||||
// State to track for building switch statements.
|
||||
bool switchExclusivelyCovered;
|
||||
Expr::EvalResult *switchCond;
|
||||
|
||||
public:
|
||||
explicit CFGBuilder() : cfg(new CFG()), // crew a new CFG
|
||||
Block(NULL), Succ(NULL),
|
||||
SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL),
|
||||
TryTerminatedBlock(NULL), badCFG(false),
|
||||
switchExclusivelyCovered(false), switchCond(0) {}
|
||||
explicit CFGBuilder(ASTContext *astContext,
|
||||
const CFG::BuildOptions &buildOpts)
|
||||
: Context(astContext), cfg(new CFG()), // crew a new CFG
|
||||
Block(NULL), Succ(NULL),
|
||||
SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL),
|
||||
TryTerminatedBlock(NULL), badCFG(false), BuildOpts(buildOpts),
|
||||
switchExclusivelyCovered(false), switchCond(0) {}
|
||||
|
||||
// buildCFG - Used by external clients to construct the CFG.
|
||||
CFG* buildCFG(const Decl *D, Stmt *Statement, ASTContext *C,
|
||||
CFG::BuildOptions BO);
|
||||
CFG* buildCFG(const Decl *D, Stmt *Statement);
|
||||
|
||||
private:
|
||||
// Visitors to walk an AST and construct the CFG.
|
||||
|
@ -460,16 +461,11 @@ static const VariableArrayType *FindVA(const Type *t) {
|
|||
/// body (compound statement). The ownership of the returned CFG is
|
||||
/// transferred to the caller. If CFG construction fails, this method returns
|
||||
/// NULL.
|
||||
CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C,
|
||||
CFG::BuildOptions BO) {
|
||||
|
||||
Context = C;
|
||||
CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement) {
|
||||
assert(cfg.get());
|
||||
if (!Statement)
|
||||
return NULL;
|
||||
|
||||
BuildOpts = BO;
|
||||
|
||||
// Create an empty block that will serve as the exit block for the CFG. Since
|
||||
// this is the first block added to the CFG, it will be implicitly registered
|
||||
// as the exit block.
|
||||
|
@ -2768,9 +2764,9 @@ CFGBlock* CFG::createBlock() {
|
|||
/// buildCFG - Constructs a CFG from an AST. Ownership of the returned
|
||||
/// CFG is returned to the caller.
|
||||
CFG* CFG::buildCFG(const Decl *D, Stmt* Statement, ASTContext *C,
|
||||
BuildOptions BO) {
|
||||
CFGBuilder Builder;
|
||||
return Builder.buildCFG(D, Statement, C, BO);
|
||||
const BuildOptions &BO) {
|
||||
CFGBuilder Builder(C, BO);
|
||||
return Builder.buildCFG(D, Statement);
|
||||
}
|
||||
|
||||
const CXXDestructorDecl *
|
||||
|
|
Loading…
Reference in New Issue