aboutsummaryrefslogtreecommitdiff
path: root/lib/Checker
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Checker')
-rw-r--r--lib/Checker/AnalysisConsumer.cpp3
-rw-r--r--lib/Checker/AnalysisManager.cpp31
-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
7 files changed, 70 insertions, 73 deletions
diff --git a/lib/Checker/AnalysisConsumer.cpp b/lib/Checker/AnalysisConsumer.cpp
index 6c7a294b1d..bbeca312f0 100644
--- a/lib/Checker/AnalysisConsumer.cpp
+++ b/lib/Checker/AnalysisConsumer.cpp
@@ -173,6 +173,7 @@ 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,
@@ -349,7 +350,7 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
}
// Execute the worklist algorithm.
- Eng.ExecuteWorkList(mgr.getStackFrame(D), mgr.getMaxNodes());
+ Eng.ExecuteWorkList(mgr.getStackFrame(D, 0), mgr.getMaxNodes());
// Release the auditor (if any) so that it doesn't monitor the graph
// created BugReporter.
diff --git a/lib/Checker/AnalysisManager.cpp b/lib/Checker/AnalysisManager.cpp
new file mode 100644
index 0000000000..339cdab80b
--- /dev/null
+++ b/lib/Checker/AnalysisManager.cpp
@@ -0,0 +1,31 @@
+//===-- AnalysisManager.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Checker/PathSensitive/AnalysisManager.h"
+#include "clang/Index/Entity.h"
+#include "clang/Index/Indexer.h"
+
+using namespace clang;
+
+const AnalysisContext *
+AnalysisManager::getAnalysisContextInAnotherTU(const Decl *D) {
+ idx::Entity Ent = idx::Entity::get(const_cast<Decl *>(D),
+ Idxer->getProgram());
+ FunctionDecl *FuncDef;
+ idx::TranslationUnit *TU;
+ llvm::tie(FuncDef, TU) = Idxer->getDefinitionFor(Ent);
+
+ if (FuncDef == 0)
+ return 0;
+
+ // This AnalysisContext wraps function definition in another translation unit.
+ // But it is still owned by the AnalysisManager associated with the current
+ // translation unit.
+ return AnaCtxMgr.getContext(FuncDef, TU);
+}
diff --git a/lib/Checker/CMakeLists.txt b/lib/Checker/CMakeLists.txt
index 259346a970..c3dab22870 100644
--- a/lib/Checker/CMakeLists.txt
+++ b/lib/Checker/CMakeLists.txt
@@ -4,6 +4,7 @@ add_clang_library(clangChecker
AdjustedReturnValueChecker.cpp
AggExprVisitor.cpp
AnalysisConsumer.cpp
+ AnalysisManager.cpp
ArrayBoundChecker.cpp
AttrNonNullChecker.cpp
BasicConstraintManager.cpp
@@ -15,7 +16,6 @@ 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
index c47e06c78f..e69de29bb2 100644
--- a/lib/Checker/CallInliner.cpp
+++ b/lib/Checker/CallInliner.cpp
@@ -1,54 +0,0 @@
-//===--- 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 18e112cc8d..5c313318c1 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, CD, Pred->getLocationContext());
+ CallEnter Loc(E, SFC->getAnalysisContext(), 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, MD, Pred->getLocationContext());
+ CallEnter Loc(MCE, SFC->getAnalysisContext(), 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 a816186a30..df790e304a 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.getCallee(),
- Block, Index);
+ GRCallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(),
+ L.getCalleeContext(), Block, Index);
ProcessCallEnter(Builder);
}
@@ -692,6 +692,12 @@ 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 26b5801068..ce7b9d8d8e 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 FunctionDecl *FD = B.getCallee();
- const StackFrameContext *LocCtx = AMgr.getStackFrame(FD,
- B.getLocationContext(),
- B.getCallExpr(),
- B.getBlock(),
- B.getIndex());
+ const StackFrameContext *LocCtx
+ = AMgr.getStackFrame(const_cast<AnalysisContext *>(B.getCalleeContext()),
+ B.getLocationContext(),
+ B.getCallExpr(),
+ B.getBlock(),
+ B.getIndex());
const GRState *state = B.getState();
state = getStoreManager().EnterStackFrame(state, LocCtx);
@@ -1886,16 +1886,29 @@ bool GRExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
if (!FD)
return false;
- if (!FD->hasBody(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;
+ }
- // Now we have the definition of the callee, create a CallEnter node.
- CallEnter Loc(CE, FD, Pred->getLocationContext());
+ // 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;
- ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
- if (N)
+ CallEnter Loc(CE, C, Pred->getLocationContext());
+ ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
Dst.Add(N);
- return true;
+ return true;
+ }
+
+ return false;
}
void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,