blob: 0279d46f2287b9d707c42bf67a0d68d1aaa5acaf [file] [log] [blame]
Zhongxing Xu66847a22009-09-11 04:13:42 +00001//===--- CallInliner.cpp - Transfer function that inlines callee ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the callee inlining transfer function.
11//
12//===----------------------------------------------------------------------===//
13
Ted Kremenek1309f9a2010-01-25 04:41:41 +000014#include "clang/Checker/PathSensitive/CheckerVisitor.h"
15#include "clang/Checker/PathSensitive/GRState.h"
Ted Kremenek97053092010-01-26 22:59:55 +000016#include "clang/Checker/Checkers/LocalCheckers.h"
Zhongxing Xu66847a22009-09-11 04:13:42 +000017
18using namespace clang;
19
20namespace {
Zhongxing Xu3ff84812009-12-23 08:56:18 +000021class CallInliner : public Checker {
Zhongxing Xu66847a22009-09-11 04:13:42 +000022public:
Zhongxing Xu3ff84812009-12-23 08:56:18 +000023 static void *getTag() {
24 static int x;
25 return &x;
26 }
Zhongxing Xu66847a22009-09-11 04:13:42 +000027
Zhongxing Xu3ff84812009-12-23 08:56:18 +000028 virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
Jakob Stoklund Olesen2b706e52010-02-25 15:47:53 +000029 virtual void EvalEndPath(GREndPathNodeBuilder &B,void *tag,GRExprEngine &Eng);
Zhongxing Xu66847a22009-09-11 04:13:42 +000030};
Zhongxing Xu66847a22009-09-11 04:13:42 +000031}
32
Zhongxing Xu3ff84812009-12-23 08:56:18 +000033void clang::RegisterCallInliner(GRExprEngine &Eng) {
34 Eng.registerCheck(new CallInliner());
35}
36
37bool CallInliner::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
38 const GRState *state = C.getState();
39 const Expr *Callee = CE->getCallee();
Ted Kremenek13976632010-02-08 16:18:51 +000040 SVal L = state->getSVal(Callee);
Zhongxing Xu62d399e2009-12-24 03:34:38 +000041
Zhongxing Xu3ff84812009-12-23 08:56:18 +000042 const FunctionDecl *FD = L.getAsFunctionDecl();
Zhongxing Xuc9f4af62009-10-13 02:36:42 +000043 if (!FD)
Zhongxing Xu3ff84812009-12-23 08:56:18 +000044 return false;
45
46 if (!FD->isThisDeclarationADefinition())
47 return false;
Zhongxing Xuc9f4af62009-10-13 02:36:42 +000048
Jakob Stoklund Olesen2b706e52010-02-25 15:47:53 +000049 GRStmtNodeBuilder &Builder = C.getNodeBuilder();
50 // Make a new LocationContext.
51 const StackFrameContext *LocCtx = C.getAnalysisManager().getStackFrame(FD,
52 C.getPredecessor()->getLocationContext(), CE,
53 Builder.getBlock(), Builder.getIndex());
54
55 CFGBlock const *Entry = &(LocCtx->getCFG()->getEntry());
56
57 assert (Entry->empty() && "Entry block must be empty.");
58
59 assert (Entry->succ_size() == 1 && "Entry block must have 1 successor.");
60
61 // Get the solitary successor.
62 CFGBlock const *SuccB = *(Entry->succ_begin());
63
64 // Construct an edge representing the starting location in the function.
65 BlockEdge Loc(Entry, SuccB, LocCtx);
66
67 state = C.getStoreManager().EnterStackFrame(state, LocCtx);
68
69 // This is a hack. We really should not use the GRStmtNodeBuilder.
70 bool isNew;
71 GRExprEngine &Eng = C.getEngine();
72 ExplodedNode *Pred = C.getPredecessor();
73
74
75 ExplodedNode *SuccN = Eng.getGraph().getNode(Loc, state, &isNew);
76 SuccN->addPredecessor(Pred, Eng.getGraph());
77 C.getNodeBuilder().Deferred.erase(Pred);
78
79 if (isNew)
80 Builder.getWorkList()->Enqueue(SuccN);
81
82 Builder.HasGeneratedNode = true;
Zhongxing Xu3ff84812009-12-23 08:56:18 +000083
84 return true;
Zhongxing Xu66847a22009-09-11 04:13:42 +000085}
Zhongxing Xu3ff84812009-12-23 08:56:18 +000086
Jakob Stoklund Olesen2b706e52010-02-25 15:47:53 +000087void CallInliner::EvalEndPath(GREndPathNodeBuilder &B, void *tag,
88 GRExprEngine &Eng) {
89 const GRState *state = B.getState();
90
91 ExplodedNode *Pred = B.getPredecessor();
92
93 const StackFrameContext *LocCtx =
94 cast<StackFrameContext>(Pred->getLocationContext());
95 // Check if this is the top level stack frame.
96 if (!LocCtx->getParent())
97 return;
98
99 const StackFrameContext *ParentSF =
100 cast<StackFrameContext>(LocCtx->getParent());
101
102 SymbolReaper SymReaper(*ParentSF->getLiveVariables(), Eng.getSymbolManager(),
103 ParentSF);
104 const Stmt *CE = LocCtx->getCallSite();
105
106 state = Eng.getStateManager().RemoveDeadBindings(state, const_cast<Stmt*>(CE),
107 SymReaper);
108
109
110 PostStmt NodeLoc(CE, LocCtx->getParent());
111
112 bool isNew;
113 ExplodedNode *Succ = Eng.getGraph().getNode(NodeLoc, state, &isNew);
114 Succ->addPredecessor(Pred, Eng.getGraph());
115
116 // When creating the new work list unit, increment the statement index to
117 // point to the statement after the CallExpr.
118 if (isNew)
119 B.getWorkList().Enqueue(Succ,
120 *const_cast<CFGBlock*>(LocCtx->getCallSiteBlock()),
121 LocCtx->getIndex() + 1);
122
123 B.HasGeneratedNode = true;
124}