blob: 2f748bd8bd5226da940377cf319874e9f7d6f3c5 [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
Zhongxing Xu3ff84812009-12-23 08:56:18 +000014#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
15#include "clang/Analysis/PathSensitive/GRState.h"
16#include "clang/Analysis/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 Xu66847a22009-09-11 04:13:42 +000029};
Zhongxing Xu66847a22009-09-11 04:13:42 +000030}
31
Zhongxing Xu3ff84812009-12-23 08:56:18 +000032void clang::RegisterCallInliner(GRExprEngine &Eng) {
33 Eng.registerCheck(new CallInliner());
34}
35
36bool CallInliner::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
37 const GRState *state = C.getState();
38 const Expr *Callee = CE->getCallee();
39 SVal L = state->getSVal(Callee);
40
41 const FunctionDecl *FD = L.getAsFunctionDecl();
Zhongxing Xuc9f4af62009-10-13 02:36:42 +000042 if (!FD)
Zhongxing Xu3ff84812009-12-23 08:56:18 +000043 return false;
44
45 if (!FD->isThisDeclarationADefinition())
46 return false;
Zhongxing Xuc9f4af62009-10-13 02:36:42 +000047
48 // Make a new LocationContext.
Zhongxing Xu3ff84812009-12-23 08:56:18 +000049 const StackFrameContext *LocCtx = C.getAnalysisManager().getStackFrame(FD,
50 C.getPredecessor()->getLocationContext(), CE);
Zhongxing Xuc9f4af62009-10-13 02:36:42 +000051
52 CFGBlock const *Entry = &(LocCtx->getCFG()->getEntry());
53
54 assert (Entry->empty() && "Entry block must be empty.");
55
56 assert (Entry->succ_size() == 1 && "Entry block must have 1 successor.");
57
58 // Get the solitary successor.
59 CFGBlock const *SuccB = *(Entry->succ_begin());
60
61 // Construct an edge representing the starting location in the function.
62 BlockEdge Loc(Entry, SuccB, LocCtx);
63
Zhongxing Xu3ff84812009-12-23 08:56:18 +000064 state = C.getStoreManager().EnterStackFrame(state, LocCtx);
Zhongxing Xuc9f4af62009-10-13 02:36:42 +000065 // This is a hack. We really should not use the GRStmtNodeBuilder.
Zhongxing Xu3ff84812009-12-23 08:56:18 +000066 bool isNew;
67 GRExprEngine &Eng = C.getEngine();
68 ExplodedNode *Pred = C.getPredecessor();
69 GRStmtNodeBuilder &Builder = C.getNodeBuilder();
70
71 ExplodedNode *SuccN = Eng.getGraph().getNode(Loc, state, &isNew);
72 SuccN->addPredecessor(Pred, Eng.getGraph());
73 C.getNodeBuilder().Deferred.erase(Pred);
74
Zhongxing Xuc9f4af62009-10-13 02:36:42 +000075 if (isNew)
76 Builder.getWorkList()->Enqueue(SuccN);
77
78 Builder.HasGeneratedNode = true;
Zhongxing Xu3ff84812009-12-23 08:56:18 +000079
80 return true;
Zhongxing Xu66847a22009-09-11 04:13:42 +000081}
Zhongxing Xu3ff84812009-12-23 08:56:18 +000082