blob: e3c5e6036a5188911cda730b5cd2893b248e7b58 [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);
Zhongxing Xu598278b2009-12-24 02:25:21 +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
Zhongxing Xu833e50e2010-02-25 06:46:30 +000049 // Now we have the definition of the callee, create a CallEnter node.
50 CallEnter Loc(CE, FD, C.getPredecessor()->getLocationContext());
51 C.addTransition(state, Loc);
Zhongxing Xu3ff84812009-12-23 08:56:18 +000052
53 return true;
Zhongxing Xu66847a22009-09-11 04:13:42 +000054}
Zhongxing Xu3ff84812009-12-23 08:56:18 +000055
Zhongxing Xu598278b2009-12-24 02:25:21 +000056void CallInliner::EvalEndPath(GREndPathNodeBuilder &B, void *tag,
57 GRExprEngine &Eng) {
58 const GRState *state = B.getState();
Zhongxing Xudf3a61b2010-02-17 08:50:05 +000059
Zhongxing Xu598278b2009-12-24 02:25:21 +000060 ExplodedNode *Pred = B.getPredecessor();
Zhongxing Xudf3a61b2010-02-17 08:50:05 +000061
Zhongxing Xu598278b2009-12-24 02:25:21 +000062 const StackFrameContext *LocCtx =
63 cast<StackFrameContext>(Pred->getLocationContext());
Zhongxing Xu598278b2009-12-24 02:25:21 +000064 // Check if this is the top level stack frame.
65 if (!LocCtx->getParent())
66 return;
67
Zhongxing Xudf3a61b2010-02-17 08:50:05 +000068 const StackFrameContext *ParentSF =
69 cast<StackFrameContext>(LocCtx->getParent());
70
71 SymbolReaper SymReaper(*ParentSF->getLiveVariables(), Eng.getSymbolManager(),
72 ParentSF);
73 const Stmt *CE = LocCtx->getCallSite();
Zhongxing Xu833e50e2010-02-25 06:46:30 +000074 // FIXME: move this logic to GRExprEngine::ProcessCallExit().
Zhongxing Xudf3a61b2010-02-17 08:50:05 +000075 state = Eng.getStateManager().RemoveDeadBindings(state, const_cast<Stmt*>(CE),
76 SymReaper);
77
Zhongxing Xu833e50e2010-02-25 06:46:30 +000078 B.GenerateCallExitNode(state);
Zhongxing Xu598278b2009-12-24 02:25:21 +000079}