ExprEngineCXX.cpp revision 89e5aaf57e20b39e35b0d068ebbc09ae736f2e1e
1//===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===//
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 defines the C++ expression evaluation engine.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/StaticAnalyzer/Core/CheckerManager.h"
15#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
16#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
17#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/StmtCXX.h"
20
21using namespace clang;
22using namespace ento;
23
24void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
25                                          ExplodedNode *Pred,
26                                          ExplodedNodeSet &Dst) {
27  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
28  const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
29  ProgramStateRef state = Pred->getState();
30  const LocationContext *LCtx = Pred->getLocationContext();
31
32  // Bind the temporary object to the value of the expression. Then bind
33  // the expression to the location of the object.
34  SVal V = state->getSVal(tempExpr, Pred->getLocationContext());
35
36  const MemRegion *R =
37    svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx);
38
39  state = state->bindLoc(loc::MemRegionVal(R), V);
40  Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R)));
41}
42
43void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
44                                             ExplodedNode *Pred,
45                                             ExplodedNodeSet &Dst) {
46  VisitCXXConstructExpr(expr, 0, Pred, Dst);
47}
48
49void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
50                                       const MemRegion *Dest,
51                                       ExplodedNode *Pred,
52                                       ExplodedNodeSet &destNodes) {
53  CXXConstructorCall Call(CE, Dest, Pred->getState(),
54                          Pred->getLocationContext());
55
56  ExplodedNodeSet DstPreVisit;
57  getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this);
58  ExplodedNodeSet DstPreCall;
59  getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit,
60                                            Call, *this);
61
62  ExplodedNodeSet DstInvalidated;
63  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
64       I != E; ++I)
65    defaultEvalCall(DstInvalidated, *I, Call);
66
67  ExplodedNodeSet DstPostCall;
68  getCheckerManager().runCheckersForPostCall(DstPostCall, DstInvalidated,
69                                             Call, *this);
70  getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this);
71}
72
73void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
74                                      const MemRegion *Dest,
75                                      const Stmt *S,
76                                      ExplodedNode *Pred,
77                                      ExplodedNodeSet &Dst) {
78  CXXDestructorCall Call(DD, S, Dest, Pred->getState(),
79                         Pred->getLocationContext());
80
81  ExplodedNodeSet DstPreCall;
82  getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
83                                            Call, *this);
84
85  ExplodedNodeSet DstInvalidated;
86  for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
87       I != E; ++I)
88    defaultEvalCall(DstInvalidated, *I, Call);
89
90  ExplodedNodeSet DstPostCall;
91  getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
92                                             Call, *this);
93}
94
95void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
96                                   ExplodedNodeSet &Dst) {
97  // FIXME: Much of this should eventually migrate to CXXAllocatorCall.
98  // Also, we need to decide how allocators actually work -- they're not
99  // really part of the CXXNewExpr because they happen BEFORE the
100  // CXXConstructExpr subexpression. See PR12014 for some discussion.
101  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
102
103  unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
104  const LocationContext *LCtx = Pred->getLocationContext();
105  DefinedOrUnknownSVal symVal =
106    svalBuilder.getConjuredSymbolVal(0, CNE, LCtx, CNE->getType(), blockCount);
107  ProgramStateRef State = Pred->getState();
108
109  // Invalidate placement args.
110  CXXAllocatorCall Call(CNE, State, LCtx);
111  State = Call.invalidateRegions(blockCount);
112
113  if (CNE->isArray()) {
114    // FIXME: allocating an array requires simulating the constructors.
115    // For now, just return a symbolicated region.
116    const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
117    QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
118    const ElementRegion *EleReg =
119      getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
120    State = State->BindExpr(CNE, Pred->getLocationContext(),
121                            loc::MemRegionVal(EleReg));
122    Bldr.generateNode(CNE, Pred, State);
123    return;
124  }
125
126  // FIXME: Once we have proper support for CXXConstructExprs inside
127  // CXXNewExpr, we need to make sure that the constructed object is not
128  // immediately invalidated here. (The placement call should happen before
129  // the constructor call anyway.)
130  FunctionDecl *FD = CNE->getOperatorNew();
131  if (FD && FD->isReservedGlobalPlacementOperator()) {
132    // Non-array placement new should always return the placement location.
133    SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);
134    State = State->BindExpr(CNE, LCtx, PlacementLoc);
135  } else {
136    State = State->BindExpr(CNE, LCtx, symVal);
137  }
138
139  // If the type is not a record, we won't have a CXXConstructExpr as an
140  // initializer. Copy the value over.
141  if (const Expr *Init = CNE->getInitializer()) {
142    if (!isa<CXXConstructExpr>(Init)) {
143      QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
144      (void)ObjTy;
145      assert(!ObjTy->isRecordType());
146      SVal Location = State->getSVal(CNE, LCtx);
147      if (isa<Loc>(Location))
148        State = State->bindLoc(cast<Loc>(Location), State->getSVal(Init, LCtx));
149    }
150  }
151
152  Bldr.generateNode(CNE, Pred, State);
153}
154
155void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
156                                    ExplodedNode *Pred, ExplodedNodeSet &Dst) {
157  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
158  ProgramStateRef state = Pred->getState();
159  Bldr.generateNode(CDE, Pred, state);
160}
161
162void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
163                                   ExplodedNode *Pred,
164                                   ExplodedNodeSet &Dst) {
165  const VarDecl *VD = CS->getExceptionDecl();
166  if (!VD) {
167    Dst.Add(Pred);
168    return;
169  }
170
171  const LocationContext *LCtx = Pred->getLocationContext();
172  SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(),
173                                 currentBuilderContext->getCurrentBlockCount());
174  ProgramStateRef state = Pred->getState();
175  state = state->bindLoc(state->getLValue(VD, LCtx), V);
176
177  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
178  Bldr.generateNode(CS, Pred, state);
179}
180
181void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
182                                    ExplodedNodeSet &Dst) {
183  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
184
185  // Get the this object region from StoreManager.
186  const LocationContext *LCtx = Pred->getLocationContext();
187  const MemRegion *R =
188    svalBuilder.getRegionManager().getCXXThisRegion(
189                                  getContext().getCanonicalType(TE->getType()),
190                                                    LCtx);
191
192  ProgramStateRef state = Pred->getState();
193  SVal V = state->getSVal(loc::MemRegionVal(R));
194  Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
195}
196