//=-- GRExprEngine.cpp - Path-Sensitive Expression-Level Dataflow ---*- 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 a meta-engine for path-sensitive dataflow analysis that
// is built on GREngine, but provides the boilerplate to execute transfer
// functions and build the ExplodedGraph at the expression level.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
#include "llvm/Support/Streams.h"
using namespace clang;
using llvm::dyn_cast;
using llvm::cast;
using llvm::APSInt;
GRExprEngine::StateTy
GRExprEngine::SetValue(StateTy St, Expr* S, const RValue& V) {
if (!StateCleaned) {
St = RemoveDeadBindings(CurrentStmt, St);
StateCleaned = true;
}
bool isBlkExpr = false;
if (S == CurrentStmt) {
isBlkExpr = getCFG().isBlkExpr(S);
if (!isBlkExpr)
return St;
}
return StateMgr.SetValue(St, S, isBlkExpr, V);
}
const GRExprEngine::StateTy::BufferTy&
GRExprEngine::SetValue(StateTy St, Expr* S, const RValue::BufferTy& RB,
StateTy::BufferTy& RetBuf) {
assert (RetBuf.empty());
for (RValue::BufferTy::const_iterator I=RB.begin(), E=RB.end(); I!=E; ++I)
RetBuf.push_back(SetValue(St, S, *I));
return RetBuf;
}
GRExprEngine::StateTy
GRExprEngine::SetValue(StateTy St, const LValue& LV, const RValue& V) {
if (LV.isUnknown())
return St;
if (!StateCleaned) {
St = RemoveDeadBindings(CurrentStmt, St);
StateCleaned = true;
}
return StateMgr.SetValue(St, LV, V);
}
void GRExprEngine::ProcessBranch(Expr* Condition, Stmt* Term,
BranchNodeBuilder& builder) {
// Remove old bindings for subexpressions.
StateTy PrevState = StateMgr.RemoveSubExprBindings(builder.getState());
RValue V = GetValue(PrevState, Condition);
switch (V.getBaseKind()) {
default:
break;
case RValue::UnknownKind:
builder.generateNode(PrevState, true);
builder.generateNode(PrevState, false);
return;
case RValue::UninitializedKind: {
NodeTy* N = builder.generateNode(PrevState, true);
if (N) {
N->markAsSink();
UninitBranches.insert(N);
}
builder.markInfeasible(false);
return;
}
}
// Get the current block counter.
GRBlockCounter BC = builder.getBlockCounter();
unsigned BlockID = builder.getTargetBlock(true)->getBlockID();