aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/wpa/clang-wpa.cpp4
-rw-r--r--include/clang/Analysis/AnalysisContext.h21
-rw-r--r--include/clang/Analysis/ProgramPoint.h12
-rw-r--r--include/clang/Checker/PathSensitive/AnalysisManager.h37
-rw-r--r--include/clang/Checker/PathSensitive/GRCoreEngine.h10
-rw-r--r--lib/Analysis/AnalysisContext.cpp5
-rw-r--r--lib/Checker/AnalysisConsumer.cpp3
-rw-r--r--lib/Checker/CMakeLists.txt2
-rw-r--r--lib/Checker/CallInliner.cpp54
-rw-r--r--lib/Checker/GRCXXExprEngine.cpp4
-rw-r--r--lib/Checker/GRCoreEngine.cpp10
-rw-r--r--lib/Checker/GRExprEngine.cpp39
-rw-r--r--tools/driver/Makefile4
13 files changed, 98 insertions, 107 deletions
diff --git a/examples/wpa/clang-wpa.cpp b/examples/wpa/clang-wpa.cpp
index 1caa3b9b68..74ec368cfb 100644
--- a/examples/wpa/clang-wpa.cpp
+++ b/examples/wpa/clang-wpa.cpp
@@ -129,7 +129,7 @@ int main(int argc, char **argv) {
AnalysisManager AMgr(TU->getASTContext(), PP.getDiagnostics(),
PP.getLangOptions(), /* PathDiagnostic */ 0,
CreateRegionStoreManager,
- CreateRangeConstraintManager, &Idxer,
+ CreateRangeConstraintManager,
/* MaxNodes */ 300000, /* MaxLoop */ 3,
/* VisualizeEG */ false, /* VisualizeEGUbi */ false,
/* PurgeDead */ true, /* EagerlyAssume */ false,
@@ -139,7 +139,7 @@ int main(int argc, char **argv) {
AMgr.getLangOptions());
GRExprEngine Eng(AMgr, TF);
- Eng.ExecuteWorkList(AMgr.getStackFrame(FD, TU), AMgr.getMaxNodes());
+ Eng.ExecuteWorkList(AMgr.getStackFrame(FD), AMgr.getMaxNodes());
return 0;
}
diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h
index 584173a33f..9ebd93b75b 100644
--- a/include/clang/Analysis/AnalysisContext.h
+++ b/include/clang/Analysis/AnalysisContext.h
@@ -34,16 +34,11 @@ class ImplicitParamDecl;
class LocationContextManager;
class StackFrameContext;
-namespace idx { class TranslationUnit; }
-
/// AnalysisContext contains the context data for the function or method under
/// analysis.
class AnalysisContext {
const Decl *D;
- // TranslationUnit is NULL if we don't have multiple translation units.
- const idx::TranslationUnit *TU;
-
// AnalysisContext owns the following data.
CFG *cfg;
bool builtCFG;
@@ -53,18 +48,14 @@ class AnalysisContext {
llvm::BumpPtrAllocator A;
bool AddEHEdges;
public:
- AnalysisContext(const Decl *d, const idx::TranslationUnit *tu,
- bool addehedges = false)
- : D(d), TU(tu), cfg(0), builtCFG(false), liveness(0), PM(0),
+ AnalysisContext(const Decl *d, bool addehedges = false)
+ : D(d), cfg(0), builtCFG(false), liveness(0), PM(0),
ReferencedBlockVars(0), AddEHEdges(addehedges) {}
~AnalysisContext();
ASTContext &getASTContext() { return D->getASTContext(); }
- const Decl *getDecl() const { return D; }
-
- const idx::TranslationUnit *getTranslationUnit() const { return TU; }
-
+ 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
@@ -91,7 +82,7 @@ class AnalysisContextManager {
public:
~AnalysisContextManager();
- AnalysisContext *getContext(const Decl *D,const idx::TranslationUnit *TU = 0);
+ AnalysisContext *getContext(const Decl *D);
// Discard all previously created AnalysisContexts.
void clear();
@@ -118,10 +109,6 @@ public:
AnalysisContext *getAnalysisContext() const { return Ctx; }
- const idx::TranslationUnit *getTranslationUnit() const {
- return Ctx->getTranslationUnit();
- }
-
const LocationContext *getParent() const { return Parent; }
bool isParentOf(const LocationContext *LC) const;
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 24bbf22640..075838d45e 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -15,7 +15,6 @@
#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT
#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
-#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "llvm/System/DataTypes.h"
#include "llvm/ADT/DenseMap.h"
@@ -27,7 +26,6 @@
namespace clang {
class LocationContext;
-class AnalysisContext;
class FunctionDecl;
class ProgramPoint {
@@ -315,16 +313,16 @@ public:
class CallEnter : public StmtPoint {
public:
- // L is caller's location context. AC is callee's AnalysisContext.
- CallEnter(const Stmt *S, const AnalysisContext *AC, const LocationContext *L)
- : StmtPoint(S, AC, CallEnterKind, L, 0) {}
+ // CallEnter uses the caller's location context.
+ CallEnter(const Stmt *S, const FunctionDecl *fd, const LocationContext *L)
+ : StmtPoint(S, fd, CallEnterKind, L, 0) {}
const Stmt *getCallExpr() const {
return static_cast<const Stmt *>(getData1());
}
- const AnalysisContext *getCalleeContext() const {
- return static_cast<const AnalysisContext *>(getData2());
+ const FunctionDecl *getCallee() const {
+ return static_cast<const FunctionDecl *>(getData2());
}
static bool classof(const ProgramPoint *Location) {
diff --git a/include/clang/Checker/PathSensitive/AnalysisManager.h b/include/clang/Checker/PathSensitive/AnalysisManager.h
index 3f673618cf..3c7cb68c09 100644
--- a/include/clang/Checker/PathSensitive/AnalysisManager.h
+++ b/include/clang/Checker/PathSensitive/AnalysisManager.h
@@ -21,11 +21,6 @@
namespace clang {
-namespace idx {
- class Indexer;
- class TranslationUnit;
-}
-
class AnalysisManager : public BugReporterData {
AnalysisContextManager AnaCtxMgr;
LocationContextManager LocCtxMgr;
@@ -40,11 +35,6 @@ class AnalysisManager : public BugReporterData {
StoreManagerCreator CreateStoreMgr;
ConstraintManagerCreator CreateConstraintMgr;
- /// \brief Provide function definitions in other translation units. This is
- /// NULL if we don't have multiple translation units. AnalysisManager does
- /// not own the Indexer.
- idx::Indexer *Idxer;
-
enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
// The maximum number of exploded nodes the analyzer will generate.
@@ -72,14 +62,13 @@ public:
AnalysisManager(ASTContext &ctx, Diagnostic &diags,
const LangOptions &lang, PathDiagnosticClient *pd,
StoreManagerCreator storemgr,
- ConstraintManagerCreator constraintmgr,
- idx::Indexer *idxer,
- unsigned maxnodes, unsigned maxloop,
+ ConstraintManagerCreator constraintmgr, 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),Idxer(idxer),
+ CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
AScope(ScopeDecl), MaxNodes(maxnodes), MaxLoop(maxloop),
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall) {}
@@ -144,10 +133,6 @@ public:
bool shouldInlineCall() const { return InlineCall; }
- bool hasIndexer() const { return Idxer != 0; }
-
- const AnalysisContext *getAnalysisContextInAnotherTU(const Decl *D);
-
CFG *getCFG(Decl const *D) {
return AnaCtxMgr.getContext(D)->getCFG();
}
@@ -160,21 +145,9 @@ public:
return AnaCtxMgr.getContext(D)->getParentMap();
}
- const AnalysisContext *getAnalysisContext(const Decl *D) {
- return AnaCtxMgr.getContext(D);
- }
-
- const StackFrameContext *getStackFrame(AnalysisContext *Ctx,
- LocationContext const *Parent,
- Stmt const *S, const CFGBlock *Blk,
- unsigned Idx) {
- return LocCtxMgr.getStackFrame(Ctx, Parent, S, Blk, Idx);
- }
-
// Get the top level stack frame.
- const StackFrameContext *getStackFrame(Decl const *D,
- const idx::TranslationUnit *TU) {
- return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0);
+ const StackFrameContext *getStackFrame(Decl const *D) {
+ return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0, 0, 0);
}
// Get a stack frame with parent.
diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h
index 317558e962..7f101dca97 100644
--- a/include/clang/Checker/PathSensitive/GRCoreEngine.h
+++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h
@@ -442,8 +442,8 @@ class GRCallEnterNodeBuilder {
// The call site.
const Stmt *CE;
- // The AnalysisContext of the callee.
- const AnalysisContext *CalleeCtx;
+ // The definition of callee.
+ const FunctionDecl *FD;
// The parent block of the CallExpr.
const CFGBlock *Block;
@@ -453,9 +453,9 @@ class GRCallEnterNodeBuilder {
public:
GRCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred,
- const Stmt *s, const AnalysisContext *callee,
+ const Stmt *s, const FunctionDecl *fd,
const CFGBlock *blk, unsigned idx)
- : Eng(eng), Pred(pred), CE(s), CalleeCtx(callee), Block(blk), Index(idx) {}
+ : Eng(eng), Pred(pred), CE(s), FD(fd), Block(blk), Index(idx) {}
const GRState *getState() const { return Pred->getState(); }
@@ -465,7 +465,7 @@ public:
const Stmt *getCallExpr() const { return CE; }
- const AnalysisContext *getCalleeContext() const { return CalleeCtx; }
+ const FunctionDecl *getCallee() const { return FD; }
const CFGBlock *getBlock() const { return Block; }
diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp
index 538d559c16..06d8aec391 100644
--- a/lib/Analysis/AnalysisContext.cpp
+++ b/lib/Analysis/AnalysisContext.cpp
@@ -83,11 +83,10 @@ LiveVariables *AnalysisContext::getLiveVariables() {
return liveness;
}
-AnalysisContext *AnalysisContextManager::getContext(const Decl *D,
- const idx::TranslationUnit *TU) {
+AnalysisContext *AnalysisContextManager::getContext(const Decl *D) {
AnalysisContext *&AC = Contexts[D];
if (!AC)
- AC = new AnalysisContext(D, TU);
+ AC = new AnalysisContext(D);
return AC;
}
diff --git a/lib/Checker/AnalysisConsumer.cpp b/lib/Checker/AnalysisConsumer.cpp
index bbeca312f0..6c7a294b1d 100644
--- a/lib/Checker/AnalysisConsumer.cpp
+++ b/lib/Checker/AnalysisConsumer.cpp
@@ -173,7 +173,6 @@ public:
Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
PP.getLangOptions(), PD,
CreateStoreMgr, CreateConstraintMgr,
- /* Indexer */ 0,
Opts.MaxNodes, Opts.MaxLoop,
Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
Opts.PurgeDead, Opts.EagerlyAssume,
@@ -350,7 +349,7 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
}
// Execute the worklist algorithm.
- Eng.ExecuteWorkList(mgr.getStackFrame(D, 0), mgr.getMaxNodes());
+ Eng.ExecuteWorkList(mgr.getStackFrame(D), mgr.getMaxNodes());
// Release the auditor (if any) so that it doesn't monitor the graph
// created BugReporter.
diff --git a/lib/Checker/CMakeLists.txt b/lib/Checker/CMakeLists.txt
index c3dab22870..259346a970 100644
--- a/lib/Checker/CMakeLists.txt
+++ b/lib/Checker/CMakeLists.txt
@@ -4,7 +4,6 @@ add_clang_library(clangChecker
AdjustedReturnValueChecker.cpp
AggExprVisitor.cpp
AnalysisConsumer.cpp
- AnalysisManager.cpp
ArrayBoundChecker.cpp
AttrNonNullChecker.cpp
BasicConstraintManager.cpp
@@ -16,6 +15,7 @@ add_clang_library(clangChecker
BuiltinFunctionChecker.cpp
CFRefCount.cpp
CallAndMessageChecker.cpp
+ CallInliner.cpp
CastSizeChecker.cpp
CastToStructChecker.cpp
CheckDeadStores.cpp
diff --git a/lib/Checker/CallInliner.cpp b/lib/Checker/CallInliner.cpp
new file mode 100644
index 0000000000..c47e06c78f
--- /dev/null
+++ b/lib/Checker/CallInliner.cpp
@@ -0,0 +1,54 @@
+//===--- CallInliner.cpp - Transfer function that inlines callee ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the callee inlining transfer function.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Checker/PathSensitive/CheckerVisitor.h"
+#include "clang/Checker/PathSensitive/GRState.h"
+#include "clang/Checker/Checkers/LocalCheckers.h"
+
+using namespace clang;
+
+namespace {
+class CallInliner : public Checker {
+public:
+ static void *getTag() {
+ static int x;
+ return &x;
+ }
+
+ virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+}
+
+void clang::RegisterCallInliner(GRExprEngine &Eng) {
+ Eng.registerCheck(new CallInliner());
+}
+
+bool CallInliner::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ const Expr *Callee = CE->getCallee();
+ SVal L = state->getSVal(Callee);
+
+ const FunctionDecl *FD = L.getAsFunctionDecl();
+ if (!FD)
+ return false;
+
+ if (!FD->hasBody(FD))
+ return false;
+
+ // Now we have the definition of the callee, create a CallEnter node.
+ CallEnter Loc(CE, FD, C.getPredecessor()->getLocationContext());
+ C.addTransition(state, Loc);
+
+ return true;
+}
+
diff --git a/lib/Checker/GRCXXExprEngine.cpp b/lib/Checker/GRCXXExprEngine.cpp
index 5c313318c1..18e112cc8d 100644
--- a/lib/Checker/GRCXXExprEngine.cpp
+++ b/lib/Checker/GRCXXExprEngine.cpp
@@ -104,7 +104,7 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
const CXXThisRegion *ThisR = getCXXThisRegion(E->getConstructor(), SFC);
- CallEnter Loc(E, SFC->getAnalysisContext(), Pred->getLocationContext());
+ CallEnter Loc(E, CD, Pred->getLocationContext());
for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(),
NE = ArgsEvaluated.end(); NI != NE; ++NI) {
const GRState *state = GetState(*NI);
@@ -157,7 +157,7 @@ void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
Builder->getBlock(),
Builder->getIndex());
const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
- CallEnter Loc(MCE, SFC->getAnalysisContext(), Pred->getLocationContext());
+ CallEnter Loc(MCE, MD, Pred->getLocationContext());
for (ExplodedNodeSet::iterator I = AllArgsEvaluated.begin(),
E = AllArgsEvaluated.end(); I != E; ++I) {
// Set up 'this' region.
diff --git a/lib/Checker/GRCoreEngine.cpp b/lib/Checker/GRCoreEngine.cpp
index df790e304a..a816186a30 100644
--- a/lib/Checker/GRCoreEngine.cpp
+++ b/lib/Checker/GRCoreEngine.cpp
@@ -227,8 +227,8 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
void GRCoreEngine::HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
unsigned Index, ExplodedNode *Pred) {
- GRCallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(),
- L.getCalleeContext(), Block, Index);
+ GRCallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(), L.getCallee(),
+ Block, Index);
ProcessCallEnter(Builder);
}
@@ -692,12 +692,6 @@ void GREndPathNodeBuilder::GenerateCallExitNode(const GRState *state) {
void GRCallEnterNodeBuilder::GenerateNode(const GRState *state,
const LocationContext *LocCtx) {
- // Check if the callee is in the same translation unit.
- if (CalleeCtx->getTranslationUnit() !=
- Pred->getLocationContext()->getTranslationUnit()) {
- assert(0 && "to be implemented");
- }
-
// Get the callee entry block.
const CFGBlock *Entry = &(LocCtx->getCFG()->getEntry());
assert(Entry->empty());
diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp
index ce7b9d8d8e..26b5801068 100644
--- a/lib/Checker/GRExprEngine.cpp
+++ b/lib/Checker/GRExprEngine.cpp
@@ -1441,12 +1441,12 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
}
void GRExprEngine::ProcessCallEnter(GRCallEnterNodeBuilder &B) {
- const StackFrameContext *LocCtx
- = AMgr.getStackFrame(const_cast<AnalysisContext *>(B.getCalleeContext()),
- B.getLocationContext(),
- B.getCallExpr(),
- B.getBlock(),
- B.getIndex());
+ const FunctionDecl *FD = B.getCallee();
+ const StackFrameContext *LocCtx = AMgr.getStackFrame(FD,
+ B.getLocationContext(),
+ B.getCallExpr(),
+ B.getBlock(),
+ B.getIndex());
const GRState *state = B.getState();
state = getStoreManager().EnterStackFrame(state, LocCtx);
@@ -1886,29 +1886,16 @@ bool GRExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
if (!FD)
return false;
- // Check if the function definition is in the same translation unit.
- if (FD->hasBody(FD)) {
- // Now we have the definition of the callee, create a CallEnter node.
- CallEnter Loc(CE, AMgr.getAnalysisContext(FD), Pred->getLocationContext());
-
- ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
- Dst.Add(N);
- return true;
- }
+ if (!FD->hasBody(FD))
+ return false;
- // Check if we can find the function definition in other translation units.
- if (AMgr.hasIndexer()) {
- const AnalysisContext *C = AMgr.getAnalysisContextInAnotherTU(FD);
- if (C == 0)
- return false;
+ // Now we have the definition of the callee, create a CallEnter node.
+ CallEnter Loc(CE, FD, Pred->getLocationContext());
- CallEnter Loc(CE, C, Pred->getLocationContext());
- ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
+ ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
+ if (N)
Dst.Add(N);
- return true;
- }
-
- return false;
+ return true;
}
void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
diff --git a/tools/driver/Makefile b/tools/driver/Makefile
index 260f53fec9..b8c91e8873 100644
--- a/tools/driver/Makefile
+++ b/tools/driver/Makefile
@@ -28,8 +28,8 @@ include $(CLANG_LEVEL)/../../Makefile.config
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter codegen \
ipo selectiondag
USEDLIBS = clangFrontend.a clangDriver.a clangCodeGen.a clangSema.a \
- clangChecker.a clangAnalysis.a clangIndex.a clangRewrite.a \
- clangAST.a clangParse.a clangLex.a clangBasic.a
+ clangChecker.a clangAnalysis.a clangRewrite.a clangAST.a \
+ clangParse.a clangLex.a clangBasic.a
include $(CLANG_LEVEL)/Makefile