This patch did the following things.
* add a Indexer to AnalysisManager
* add a InlineCallInAnotherTU() to GRExprEngine, which tries to find
the definition of the callee in other translation units.
* add a new ProgramPoint: FarCallEnter which indicates we are going to
enter a function in another translation unit. And associated builder
classes.
* now stop at GRFarCallEnterNodeBuilder::GenerateNode(). Here I plan
to create a new GRExprEngine with a input state and an output state
set. After it finishes running, add all output nodes into the WList.
Index: include/clang/Analysis/ProgramPoint.h
===================================================================
--- include/clang/Analysis/ProgramPoint.h (版本 107853)
+++ include/clang/Analysis/ProgramPoint.h (工作副本)
@@ -28,11 +28,14 @@
class LocationContext;
class FunctionDecl;
+namespace idx { class TranslationUnit; }
+
class ProgramPoint {
public:
enum Kind { BlockEdgeKind,
BlockEntranceKind,
BlockExitKind,
+ FarCallEnterKind,
PreStmtKind,
PostStmtKind,
PreLoadKind,
@@ -341,7 +344,21 @@
}
};
+class FarCallEnter : public ProgramPoint {
+public:
+ FarCallEnter(const FunctionDecl *FD, idx::TranslationUnit *TU,
+ const LocationContext *L)
+ : ProgramPoint(FD, TU, FarCallEnterKind, L, 0) {}
+ const FunctionDecl *getCallee() const {
+ return static_cast<const FunctionDecl *>(getData1());
+ }
+
+ static bool classof(const ProgramPoint *Location) {
+ return Location->getKind() == FarCallEnterKind;
+ }
+};
+
} // end namespace clang
Index: include/clang/Checker/PathSensitive/GRExprEngine.h
===================================================================
--- include/clang/Checker/PathSensitive/GRExprEngine.h (版本 107853)
+++ include/clang/Checker/PathSensitive/GRExprEngine.h (工作副本)
@@ -196,6 +196,8 @@
/// Generate the first post callsite node.
void ProcessCallExit(GRCallExitNodeBuilder &builder);
+ void ProcessFarCallEnter(GRFarCallEnterNodeBuilder &builder);
+
/// Called by GRCoreEngine when the analysis worklist has terminated.
void ProcessEndWorklist(bool hasWorkRemaining);
@@ -473,6 +475,8 @@
const void *tag, bool isLoad);
bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred);
+ bool InlineCallInAnotherTU(ExplodedNodeSet &Dst, const CallExpr *CE,
+ ExplodedNode *Pred);
};
} // end clang namespace
Index: include/clang/Checker/PathSensitive/GRCoreEngine.h
===================================================================
--- include/clang/Checker/PathSensitive/GRCoreEngine.h (版本 107853)
+++ include/clang/Checker/PathSensitive/GRCoreEngine.h (工作副本)
@@ -42,6 +42,7 @@
friend class GREndPathNodeBuilder;
friend class GRCallEnterNodeBuilder;
friend class GRCallExitNodeBuilder;
+ friend class GRFarCallEnterNodeBuilder;
GRSubEngine& SubEngine;
@@ -76,6 +77,8 @@
void HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
unsigned Index, ExplodedNode *Pred);
void HandleCallExit(const CallExit &L, ExplodedNode *Pred);
+ void HandleFarCallEnter(const FarCallEnter &L, const CFGBlock *Block,
+ unsigned Index, ExplodedNode *Pred);
/// Get the initial state from the subengine.
const GRState* getInitialState(const LocationContext *InitLoc) {
@@ -101,6 +104,7 @@
void ProcessCallEnter(GRCallEnterNodeBuilder &Builder);
void ProcessCallExit(GRCallExitNodeBuilder &Builder);
+ void ProcessFarCallEnter(GRFarCallEnterNodeBuilder &Builder);
private:
GRCoreEngine(const GRCoreEngine&); // Do not implement.
@@ -474,6 +478,35 @@
void GenerateNode(const GRState *state, const LocationContext *LocCtx);
};
+class GRFarCallEnterNodeBuilder {
+ GRCoreEngine &Eng;
+
+ const ExplodedNode *Pred;
+
+ // The definition of callee.
+ const FunctionDecl *FD;
+
+ // The parent block of the CallExpr.
+ const CFGBlock *Block;
+
+ // The CFGBlock index of the CallExpr.
+ unsigned Index;
+
+public:
+ GRFarCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred,
+ const FunctionDecl *fd, const CFGBlock *blk,
+ unsigned idx)
+ : Eng(eng), Pred(pred), FD(fd), Block(blk), Index(idx) {}
+ const GRState *getState() const { return Pred->getState(); }
+ const LocationContext *getLocationContext() const {
+ return Pred->getLocationContext();
+ }
+ const FunctionDecl *getCallee() const { return FD; }
+ const CFGBlock *getBlock() const { return Block; }
+ unsigned getIndex() const { return Index; }
+ void GenerateNode(const GRState *state, const LocationContext *LocCtx);
+};
+
class GRCallExitNodeBuilder {
GRCoreEngine &Eng;
const ExplodedNode *Pred;
Index: include/clang/Checker/PathSensitive/GRSubEngine.h
===================================================================
--- include/clang/Checker/PathSensitive/GRSubEngine.h (版本 107853)
+++ include/clang/Checker/PathSensitive/GRSubEngine.h (工作副本)
@@ -31,6 +31,7 @@
class GREndPathNodeBuilder;
class GRCallEnterNodeBuilder;
class GRCallExitNodeBuilder;
+class GRFarCallEnterNodeBuilder;
class LocationContext;
class GRSubEngine {
@@ -73,6 +74,8 @@
// Generate the first post callsite node.
virtual void ProcessCallExit(GRCallExitNodeBuilder &builder) = 0;
+
+ virtual void ProcessFarCallEnter(GRFarCallEnterNodeBuilder &builder) = 0;
/// Called by ConstraintManager. Used to call checker-specific
/// logic for handling assumptions on symbolic values.
Index: include/clang/Checker/PathSensitive/AnalysisManager.h
===================================================================
--- include/clang/Checker/PathSensitive/AnalysisManager.h (版本 107853)
+++ include/clang/Checker/PathSensitive/AnalysisManager.h (工作副本)
@@ -18,9 +18,15 @@
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include "clang/Checker/BugReporter/PathDiagnostic.h"
+#include "clang/Index/Program.h"
+#include "clang/Index/Indexer.h"
namespace clang {
+namespace idx {
+class TranslationUnit;
+}
+
class AnalysisManager : public BugReporterData {
AnalysisContextManager AnaCtxMgr;
LocationContextManager LocCtxMgr;
@@ -35,6 +41,9 @@
StoreManagerCreator CreateStoreMgr;
ConstraintManagerCreator CreateConstraintMgr;
+ // Provide function definitions in other translation units.
+ idx::Indexer *Idxer;
+
enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
// The maximum number of exploded nodes the analyzer will generate.
@@ -62,13 +71,14 @@
AnalysisManager(ASTContext &ctx, Diagnostic &diags,
const LangOptions &lang, PathDiagnosticClient *pd,
StoreManagerCreator storemgr,
- ConstraintManagerCreator constraintmgr, unsigned maxnodes,
- unsigned maxloop,
+ ConstraintManagerCreator constraintmgr,
+ idx::Indexer *idxer,
+ unsigned maxnodes, unsigned maxloop,
bool vizdot, bool vizubi, bool purge, bool eager, bool trim,
bool inlinecall)
: Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd),
- CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
+ CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),Idxer(idxer),
AScope(ScopeDecl), MaxNodes(maxnodes), MaxLoop(maxloop),
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall) {}
@@ -157,6 +167,17 @@
unsigned Idx) {
return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S, Blk,Idx);
}
+
+ bool isInterfileAnalysis() const {
+ return Idxer != 0;
+ }
+
+ std::pair<FunctionDecl *, idx::TranslationUnit *>
+ getFunctionDefinition(const FunctionDecl *D) {
+ idx::Entity Ent = idx::Entity::get(const_cast<FunctionDecl *>(D),
+ Idxer->getProgram());
+ return Idxer->getDefinitionFor(Ent);
+ }
};
}
Index: tools/driver/Makefile
===================================================================
--- tools/driver/Makefile (版本 107853)
+++ tools/driver/Makefile (工作副本)
@@ -28,8 +28,8 @@
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter codegen \
ipo selectiondag
USEDLIBS = clangFrontend.a clangDriver.a clangCodeGen.a clangSema.a \
- clangChecker.a clangAnalysis.a clangRewrite.a clangAST.a \
- clangParse.a clangLex.a clangBasic.a
+ clangChecker.a clangAnalysis.a clangIndex.a clangRewrite.a \
+ clangAST.a clangParse.a clangLex.a clangBasic.a
include $(CLANG_LEVEL)/Makefile
Index: lib/Checker/AnalysisConsumer.cpp
===================================================================
--- lib/Checker/AnalysisConsumer.cpp (版本 107853)
+++ lib/Checker/AnalysisConsumer.cpp (工作副本)
@@ -172,7 +172,7 @@
Ctx = &Context;
Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
PP.getLangOptions(), PD,
- CreateStoreMgr, CreateConstraintMgr,
+ CreateStoreMgr, CreateConstraintMgr, 0,
Opts.MaxNodes, Opts.MaxLoop,
Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
Opts.PurgeDead, Opts.EagerlyAssume,
Index: lib/Checker/GRCoreEngine.cpp
===================================================================
--- lib/Checker/GRCoreEngine.cpp (版本 107853)
+++ lib/Checker/GRCoreEngine.cpp (工作副本)
@@ -148,6 +148,10 @@
SubEngine.ProcessCallEnter(Builder);
}
+void GRCoreEngine::ProcessFarCallEnter(GRFarCallEnterNodeBuilder &Builder) {
+ SubEngine.ProcessFarCallEnter(Builder);
+}
+
void GRCoreEngine::ProcessCallExit(GRCallExitNodeBuilder &Builder) {
SubEngine.ProcessCallExit(Builder);
}
@@ -209,6 +213,11 @@
WU.getIndex(), Node);
break;
+ case ProgramPoint::FarCallEnterKind:
+ HandleFarCallEnter(cast<FarCallEnter>(Node->getLocation()),
+ WU.getBlock(), WU.getIndex(), Node);
+ break;
+
case ProgramPoint::CallExitKind:
HandleCallExit(cast<CallExit>(Node->getLocation()), Node);
break;
@@ -232,6 +241,13 @@
ProcessCallEnter(Builder);
}
+void GRCoreEngine::HandleFarCallEnter(const FarCallEnter &L,
+ const CFGBlock *Block,
+ unsigned Index, ExplodedNode *Pred) {
+ GRFarCallEnterNodeBuilder Builder(*this, Pred, L.getCallee(), Block, Index);
+ ProcessFarCallEnter(Builder);
+}
+
void GRCoreEngine::HandleCallExit(const CallExit &L, ExplodedNode *Pred) {
GRCallExitNodeBuilder Builder(*this, Pred);
ProcessCallExit(Builder);
@@ -435,7 +451,7 @@
assert (!N->isSink());
// Check if this node entered a callee.
- if (isa<CallEnter>(N->getLocation())) {
+ if (isa<CallEnter>(N->getLocation()) || isa<FarCallEnter>(N->getLocation())) {
// Still use the index of the CallExpr. It's needed to create the callee
// StackFrameContext.
Eng.WList->Enqueue(N, B, Idx);
@@ -711,6 +727,11 @@
Eng.WList->Enqueue(Node);
}
+void GRFarCallEnterNodeBuilder::GenerateNode(const GRState *state,
+ const LocationContext *LocCtx) {
+ assert(0 && "Okay, we get here. Create a new GRExprEngine with the initial state.");
+}
+
void GRCallExitNodeBuilder::GenerateNode(const GRState *state) {
// Get the callee's location context.
const StackFrameContext *LocCtx
Index: lib/Checker/GRExprEngine.cpp
===================================================================
--- lib/Checker/GRExprEngine.cpp (版本 107853)
+++ lib/Checker/GRExprEngine.cpp (工作副本)
@@ -18,6 +18,7 @@
#include "clang/Checker/PathSensitive/GRExprEngine.h"
#include "clang/Checker/PathSensitive/GRExprEngineBuilders.h"
#include "clang/Checker/PathSensitive/Checker.h"
+#include "clang/Index/TranslationUnit.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/StmtObjC.h"
@@ -1453,6 +1454,20 @@
B.GenerateNode(state, LocCtx);
}
+void GRExprEngine::ProcessFarCallEnter(GRFarCallEnterNodeBuilder &B) {
+ const FunctionDecl *FD = B.getCallee();
+ // Get the call expr.
+ const CFGBlock &Block = *B.getBlock();
+ unsigned Idx = B.getIndex();
+ Stmt *S = Block[Idx].getStmt();
+ // Create the stack frame for the callee.
+ const StackFrameContext *LocCtx = AMgr.getStackFrame(FD,
+ B.getLocationContext(),
+ S, &Block, Idx);
+ // FIXME: Marshal information to get the new state. Use the old state for now.
+ B.GenerateNode(B.getState(), LocCtx);
+}
+
void GRExprEngine::ProcessCallExit(GRCallExitNodeBuilder &B) {
const GRState *state = B.getState();
const ExplodedNode *Pred = B.getPredecessor();
@@ -1897,6 +1912,29 @@
return true;
}
+bool GRExprEngine::InlineCallInAnotherTU(ExplodedNodeSet &Dst,
+ const CallExpr *CE, ExplodedNode *Pred) {
+ const GRState *state = GetState(Pred);
+ const Expr *Callee = CE->getCallee();
+ SVal L = state->getSVal(Callee);
+ const FunctionDecl *FD = L.getAsFunctionDecl();
+ if (!FD)
+ return false;
+
+ // Get the definition and translation unit of the callee.
+ FunctionDecl *FuncDef;
+ idx::TranslationUnit *TU;
+ llvm::tie(FuncDef, TU) = AMgr.getFunctionDefinition(FD);
+
+ if (!FD)
+ return false;
+ FarCallEnter Loc(FD, TU, Pred->getLocationContext());
+ ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
+ if (N)
+ Dst.Add(N);
+ return true;
+}
+
void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
CallExpr::arg_iterator AI,
CallExpr::arg_iterator AE,
@@ -1979,8 +2017,10 @@
else if (AMgr.shouldInlineCall() && InlineCall(Dst, CE, *DI)) {
// Callee is inlined. We shouldn't do post call checking.
return;
- }
- else {
+ } else if (AMgr.isInterfileAnalysis() &&
+ InlineCallInAnotherTU(Dst, CE, *DI)) {
+ return;
+ } else {
for (ExplodedNodeSet::iterator DI_Checker = DstChecker.begin(),
DE_Checker = DstChecker.end();
DI_Checker != DE_Checker; ++DI_Checker) {
Index: examples/wpa/clang-wpa.cpp
===================================================================
--- examples/wpa/clang-wpa.cpp (版本 107853)
+++ examples/wpa/clang-wpa.cpp (工作副本)
@@ -129,7 +129,7 @@
AnalysisManager AMgr(TU->getASTContext(), PP.getDiagnostics(),
PP.getLangOptions(), /* PathDiagnostic */ 0,
CreateRegionStoreManager,
- CreateRangeConstraintManager,
+ CreateRangeConstraintManager, &Idxer,
/* MaxNodes */ 300000, /* MaxLoop */ 3,
/* VisualizeEG */ false, /* VisualizeEGUbi */ false,
/* PurgeDead */ true, /* EagerlyAssume */ false,
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits