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