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 
21 using namespace clang;
22 using namespace ento;
23 
24 void 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 
43 void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
44                                              ExplodedNode *Pred,
45                                              ExplodedNodeSet &Dst) {
46   VisitCXXConstructExpr(expr, 0, Pred, Dst);
47 }
48 
49 void 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 
73 void 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 
95 void 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   Bldr.generateNode(CNE, Pred, State);
140 }
141 
142 void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
143                                     ExplodedNode *Pred, ExplodedNodeSet &Dst) {
144   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
145   ProgramStateRef state = Pred->getState();
146   Bldr.generateNode(CDE, Pred, state);
147 }
148 
149 void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
150                                    ExplodedNode *Pred,
151                                    ExplodedNodeSet &Dst) {
152   const VarDecl *VD = CS->getExceptionDecl();
153   if (!VD) {
154     Dst.Add(Pred);
155     return;
156   }
157 
158   const LocationContext *LCtx = Pred->getLocationContext();
159   SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(),
160                                  currentBuilderContext->getCurrentBlockCount());
161   ProgramStateRef state = Pred->getState();
162   state = state->bindLoc(state->getLValue(VD, LCtx), V);
163 
164   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
165   Bldr.generateNode(CS, Pred, state);
166 }
167 
168 void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
169                                     ExplodedNodeSet &Dst) {
170   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
171 
172   // Get the this object region from StoreManager.
173   const LocationContext *LCtx = Pred->getLocationContext();
174   const MemRegion *R =
175     svalBuilder.getRegionManager().getCXXThisRegion(
176                                   getContext().getCanonicalType(TE->getType()),
177                                                     LCtx);
178 
179   ProgramStateRef state = Pred->getState();
180   SVal V = state->getSVal(loc::MemRegionVal(R));
181   Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
182 }
183