1a9ce612fSTed Kremenek //=-- ExprEngineC.cpp - ExprEngine support for C expressions ----*- C++ -*-===//
2a9ce612fSTed Kremenek //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a9ce612fSTed Kremenek //
7a9ce612fSTed Kremenek //===----------------------------------------------------------------------===//
8a9ce612fSTed Kremenek //
9a9ce612fSTed Kremenek //  This file defines ExprEngine's support for C expressions.
10a9ce612fSTed Kremenek //
11a9ce612fSTed Kremenek //===----------------------------------------------------------------------===//
12a9ce612fSTed Kremenek 
13d7d2b1feSBenjamin Kramer #include "clang/AST/ExprCXX.h"
1464c01f7bSDevin Coughlin #include "clang/AST/DeclCXX.h"
15a9ce612fSTed Kremenek #include "clang/StaticAnalyzer/Core/CheckerManager.h"
16a9ce612fSTed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
17a9ce612fSTed Kremenek 
18a9ce612fSTed Kremenek using namespace clang;
19a9ce612fSTed Kremenek using namespace ento;
20a9ce612fSTed Kremenek using llvm::APSInt;
21a9ce612fSTed Kremenek 
229fc8faf9SAdrian Prantl /// Optionally conjure and return a symbol for offset when processing
238ee82ed8SGeorge Karpenkov /// an expression \p Expression.
248ee82ed8SGeorge Karpenkov /// If \p Other is a location, conjure a symbol for \p Symbol
258ee82ed8SGeorge Karpenkov /// (offset) if it is unknown so that memory arithmetic always
268ee82ed8SGeorge Karpenkov /// results in an ElementRegion.
278ee82ed8SGeorge Karpenkov /// \p Count The number of times the current basic block was visited.
conjureOffsetSymbolOnLocation(SVal Symbol,SVal Other,Expr * Expression,SValBuilder & svalBuilder,unsigned Count,const LocationContext * LCtx)288ee82ed8SGeorge Karpenkov static SVal conjureOffsetSymbolOnLocation(
298ee82ed8SGeorge Karpenkov     SVal Symbol, SVal Other, Expr* Expression, SValBuilder &svalBuilder,
308ee82ed8SGeorge Karpenkov     unsigned Count, const LocationContext *LCtx) {
318ee82ed8SGeorge Karpenkov   QualType Ty = Expression->getType();
32*96ccb690SBalazs Benics   if (isa<Loc>(Other) && Ty->isIntegralOrEnumerationType() &&
338ee82ed8SGeorge Karpenkov       Symbol.isUnknown()) {
348ee82ed8SGeorge Karpenkov     return svalBuilder.conjureSymbolVal(Expression, LCtx, Ty, Count);
358ee82ed8SGeorge Karpenkov   }
368ee82ed8SGeorge Karpenkov   return Symbol;
378ee82ed8SGeorge Karpenkov }
388ee82ed8SGeorge Karpenkov 
VisitBinaryOperator(const BinaryOperator * B,ExplodedNode * Pred,ExplodedNodeSet & Dst)39a9ce612fSTed Kremenek void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
40a9ce612fSTed Kremenek                                      ExplodedNode *Pred,
41a9ce612fSTed Kremenek                                      ExplodedNodeSet &Dst) {
42876e34b7STed Kremenek 
43a9ce612fSTed Kremenek   Expr *LHS = B->getLHS()->IgnoreParens();
44a9ce612fSTed Kremenek   Expr *RHS = B->getRHS()->IgnoreParens();
45a9ce612fSTed Kremenek 
46876e34b7STed Kremenek   // FIXME: Prechecks eventually go in ::Visit().
47a9ce612fSTed Kremenek   ExplodedNodeSet CheckedSet;
48876e34b7STed Kremenek   ExplodedNodeSet Tmp2;
49876e34b7STed Kremenek   getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, B, *this);
50a9ce612fSTed Kremenek 
51a9ce612fSTed Kremenek   // With both the LHS and RHS evaluated, process the operation itself.
52876e34b7STed Kremenek   for (ExplodedNodeSet::iterator it=CheckedSet.begin(), ei=CheckedSet.end();
53876e34b7STed Kremenek          it != ei; ++it) {
54a9ce612fSTed Kremenek 
5549b1e38eSTed Kremenek     ProgramStateRef state = (*it)->getState();
56632e3b7eSTed Kremenek     const LocationContext *LCtx = (*it)->getLocationContext();
57632e3b7eSTed Kremenek     SVal LeftV = state->getSVal(LHS, LCtx);
58632e3b7eSTed Kremenek     SVal RightV = state->getSVal(RHS, LCtx);
59a9ce612fSTed Kremenek 
60a9ce612fSTed Kremenek     BinaryOperator::Opcode Op = B->getOpcode();
61a9ce612fSTed Kremenek 
62a9ce612fSTed Kremenek     if (Op == BO_Assign) {
63a9ce612fSTed Kremenek       // EXPERIMENTAL: "Conjured" symbols.
64a9ce612fSTed Kremenek       // FIXME: Handle structs.
6551090d5fSAnna Zaks       if (RightV.isUnknown()) {
66d94854a4STed Kremenek         unsigned Count = currBldrCtx->blockCount();
670dbb783cSCraig Topper         RightV = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx,
680dbb783cSCraig Topper                                               Count);
69a9ce612fSTed Kremenek       }
70a9ce612fSTed Kremenek       // Simulate the effects of a "store":  bind the value of the RHS
71a9ce612fSTed Kremenek       // to the L-Value represented by the LHS.
7294a7b849SAnna Zaks       SVal ExprVal = B->isGLValue() ? LeftV : RightV;
73632e3b7eSTed Kremenek       evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, LCtx, ExprVal),
74632e3b7eSTed Kremenek                 LeftV, RightV);
75a9ce612fSTed Kremenek       continue;
76a9ce612fSTed Kremenek     }
77a9ce612fSTed Kremenek 
78a9ce612fSTed Kremenek     if (!B->isAssignmentOp()) {
79d94854a4STed Kremenek       StmtNodeBuilder Bldr(*it, Tmp2, *currBldrCtx);
801655aee1SAnna Zaks 
811655aee1SAnna Zaks       if (B->isAdditiveOp()) {
821655aee1SAnna Zaks         // TODO: This can be removed after we enable history tracking with
831655aee1SAnna Zaks         // SymSymExpr.
84d94854a4STed Kremenek         unsigned Count = currBldrCtx->blockCount();
858ee82ed8SGeorge Karpenkov         RightV = conjureOffsetSymbolOnLocation(
868ee82ed8SGeorge Karpenkov             RightV, LeftV, RHS, svalBuilder, Count, LCtx);
878ee82ed8SGeorge Karpenkov         LeftV = conjureOffsetSymbolOnLocation(
888ee82ed8SGeorge Karpenkov             LeftV, RightV, LHS, svalBuilder, Count, LCtx);
891655aee1SAnna Zaks       }
901655aee1SAnna Zaks 
9162ac9ecaSJordan Rose       // Although we don't yet model pointers-to-members, we do need to make
9262ac9ecaSJordan Rose       // sure that the members of temporaries have a valid 'this' pointer for
9362ac9ecaSJordan Rose       // other checks.
9462ac9ecaSJordan Rose       if (B->getOpcode() == BO_PtrMemD)
9562ac9ecaSJordan Rose         state = createTemporaryRegionIfNeeded(state, LCtx, LHS);
9662ac9ecaSJordan Rose 
97a9ce612fSTed Kremenek       // Process non-assignments except commas or short-circuited
98a9ce612fSTed Kremenek       // logical expressions (LAnd and LOr).
99a9ce612fSTed Kremenek       SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType());
10085a34aa2SGeorge Karpenkov       if (!Result.isUnknown()) {
10185a34aa2SGeorge Karpenkov         state = state->BindExpr(B, LCtx, Result);
10249885b12SCsaba Dabis       } else {
10349885b12SCsaba Dabis         // If we cannot evaluate the operation escape the operands.
1045882e6f3SGabor Horvath         state = escapeValues(state, LeftV, PSK_EscapeOther);
1055882e6f3SGabor Horvath         state = escapeValues(state, RightV, PSK_EscapeOther);
106a9ce612fSTed Kremenek       }
107a9ce612fSTed Kremenek 
108e594034fSAnna Zaks       Bldr.generateNode(B, *it, state);
109a9ce612fSTed Kremenek       continue;
110a9ce612fSTed Kremenek     }
111a9ce612fSTed Kremenek 
112a9ce612fSTed Kremenek     assert (B->isCompoundAssignmentOp());
113a9ce612fSTed Kremenek 
114a9ce612fSTed Kremenek     switch (Op) {
115a9ce612fSTed Kremenek       default:
11683d382b1SDavid Blaikie         llvm_unreachable("Invalid opcode for compound assignment.");
117a9ce612fSTed Kremenek       case BO_MulAssign: Op = BO_Mul; break;
118a9ce612fSTed Kremenek       case BO_DivAssign: Op = BO_Div; break;
119a9ce612fSTed Kremenek       case BO_RemAssign: Op = BO_Rem; break;
120a9ce612fSTed Kremenek       case BO_AddAssign: Op = BO_Add; break;
121a9ce612fSTed Kremenek       case BO_SubAssign: Op = BO_Sub; break;
122a9ce612fSTed Kremenek       case BO_ShlAssign: Op = BO_Shl; break;
123a9ce612fSTed Kremenek       case BO_ShrAssign: Op = BO_Shr; break;
124a9ce612fSTed Kremenek       case BO_AndAssign: Op = BO_And; break;
125a9ce612fSTed Kremenek       case BO_XorAssign: Op = BO_Xor; break;
126a9ce612fSTed Kremenek       case BO_OrAssign:  Op = BO_Or;  break;
127a9ce612fSTed Kremenek     }
128a9ce612fSTed Kremenek 
129a9ce612fSTed Kremenek     // Perform a load (the LHS).  This performs the checks for
130a9ce612fSTed Kremenek     // null dereferences, and so on.
131876e34b7STed Kremenek     ExplodedNodeSet Tmp;
132876e34b7STed Kremenek     SVal location = LeftV;
133a85f38baSTed Kremenek     evalLoad(Tmp, B, LHS, *it, state, location);
134a9ce612fSTed Kremenek 
135876e34b7STed Kremenek     for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E;
136876e34b7STed Kremenek          ++I) {
137876e34b7STed Kremenek 
138876e34b7STed Kremenek       state = (*I)->getState();
139632e3b7eSTed Kremenek       const LocationContext *LCtx = (*I)->getLocationContext();
140632e3b7eSTed Kremenek       SVal V = state->getSVal(LHS, LCtx);
141a9ce612fSTed Kremenek 
142a9ce612fSTed Kremenek       // Get the computation type.
143a9ce612fSTed Kremenek       QualType CTy =
144a9ce612fSTed Kremenek         cast<CompoundAssignOperator>(B)->getComputationResultType();
145a9ce612fSTed Kremenek       CTy = getContext().getCanonicalType(CTy);
146a9ce612fSTed Kremenek 
147a9ce612fSTed Kremenek       QualType CLHSTy =
148a9ce612fSTed Kremenek         cast<CompoundAssignOperator>(B)->getComputationLHSType();
149a9ce612fSTed Kremenek       CLHSTy = getContext().getCanonicalType(CLHSTy);
150a9ce612fSTed Kremenek 
151a9ce612fSTed Kremenek       QualType LTy = getContext().getCanonicalType(LHS->getType());
152a9ce612fSTed Kremenek 
153a9ce612fSTed Kremenek       // Promote LHS.
154a9ce612fSTed Kremenek       V = svalBuilder.evalCast(V, CLHSTy, LTy);
155a9ce612fSTed Kremenek 
156a9ce612fSTed Kremenek       // Compute the result of the operation.
157a9ce612fSTed Kremenek       SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy),
158a9ce612fSTed Kremenek                                          B->getType(), CTy);
159a9ce612fSTed Kremenek 
160a9ce612fSTed Kremenek       // EXPERIMENTAL: "Conjured" symbols.
161a9ce612fSTed Kremenek       // FIXME: Handle structs.
162a9ce612fSTed Kremenek 
163a9ce612fSTed Kremenek       SVal LHSVal;
164a9ce612fSTed Kremenek 
165a636fbe7SAnna Zaks       if (Result.isUnknown()) {
166a9ce612fSTed Kremenek         // The symbolic value is actually for the type of the left-hand side
167a9ce612fSTed Kremenek         // expression, not the computation type, as this is the value the
168a9ce612fSTed Kremenek         // LValue on the LHS will bind to.
1690dbb783cSCraig Topper         LHSVal = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, LTy,
170d94854a4STed Kremenek                                               currBldrCtx->blockCount());
171a9ce612fSTed Kremenek         // However, we need to convert the symbol to the computation type.
172a9ce612fSTed Kremenek         Result = svalBuilder.evalCast(LHSVal, CTy, LTy);
173a9ce612fSTed Kremenek       }
174a9ce612fSTed Kremenek       else {
175a9ce612fSTed Kremenek         // The left-hand side may bind to a different value then the
176a9ce612fSTed Kremenek         // computation type.
177a9ce612fSTed Kremenek         LHSVal = svalBuilder.evalCast(Result, LTy, CTy);
178a9ce612fSTed Kremenek       }
179a9ce612fSTed Kremenek 
180a9ce612fSTed Kremenek       // In C++, assignment and compound assignment operators return an
181a9ce612fSTed Kremenek       // lvalue.
18294a7b849SAnna Zaks       if (B->isGLValue())
183632e3b7eSTed Kremenek         state = state->BindExpr(B, LCtx, location);
184a9ce612fSTed Kremenek       else
185632e3b7eSTed Kremenek         state = state->BindExpr(B, LCtx, Result);
186a9ce612fSTed Kremenek 
187876e34b7STed Kremenek       evalStore(Tmp2, B, LHS, *I, state, location, LHSVal);
188a9ce612fSTed Kremenek     }
189a9ce612fSTed Kremenek   }
190a9ce612fSTed Kremenek 
191876e34b7STed Kremenek   // FIXME: postvisits eventually go in ::Visit()
192876e34b7STed Kremenek   getCheckerManager().runCheckersForPostStmt(Dst, Tmp2, B, *this);
193a9ce612fSTed Kremenek }
194a9ce612fSTed Kremenek 
VisitBlockExpr(const BlockExpr * BE,ExplodedNode * Pred,ExplodedNodeSet & Dst)195a9ce612fSTed Kremenek void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
196a9ce612fSTed Kremenek                                 ExplodedNodeSet &Dst) {
197a9ce612fSTed Kremenek 
198a9ce612fSTed Kremenek   CanQualType T = getContext().getCanonicalType(BE->getType());
199fd727748STed Kremenek 
200ebeed880SDevin Coughlin   const BlockDecl *BD = BE->getBlockDecl();
201fd727748STed Kremenek   // Get the value of the block itself.
202ebeed880SDevin Coughlin   SVal V = svalBuilder.getBlockPointer(BD, T,
203d2a807d8SAnna Zaks                                        Pred->getLocationContext(),
204d2a807d8SAnna Zaks                                        currBldrCtx->blockCount());
205a9ce612fSTed Kremenek 
206fd727748STed Kremenek   ProgramStateRef State = Pred->getState();
207fd727748STed Kremenek 
208fd727748STed Kremenek   // If we created a new MemRegion for the block, we should explicitly bind
209fd727748STed Kremenek   // the captured variables.
210fd727748STed Kremenek   if (const BlockDataRegion *BDR =
211fd727748STed Kremenek       dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
212fd727748STed Kremenek 
213fd727748STed Kremenek     BlockDataRegion::referenced_vars_iterator I = BDR->referenced_vars_begin(),
214fd727748STed Kremenek                                               E = BDR->referenced_vars_end();
215fd727748STed Kremenek 
216ebeed880SDevin Coughlin     auto CI = BD->capture_begin();
217ebeed880SDevin Coughlin     auto CE = BD->capture_end();
218fd727748STed Kremenek     for (; I != E; ++I) {
219ebeed880SDevin Coughlin       const VarRegion *capturedR = I.getCapturedRegion();
22098db1f99SAdam Balogh       const TypedValueRegion *originalR = I.getOriginalRegion();
221ebeed880SDevin Coughlin 
222ebeed880SDevin Coughlin       // If the capture had a copy expression, use the result of evaluating
223ebeed880SDevin Coughlin       // that expression, otherwise use the original value.
224ebeed880SDevin Coughlin       // We rely on the invariant that the block declaration's capture variables
225ebeed880SDevin Coughlin       // are a prefix of the BlockDataRegion's referenced vars (which may include
226ebeed880SDevin Coughlin       // referenced globals, etc.) to enable fast lookup of the capture for a
227ebeed880SDevin Coughlin       // given referenced var.
228ebeed880SDevin Coughlin       const Expr *copyExpr = nullptr;
229ebeed880SDevin Coughlin       if (CI != CE) {
230ebeed880SDevin Coughlin         assert(CI->getVariable() == capturedR->getDecl());
231ebeed880SDevin Coughlin         copyExpr = CI->getCopyExpr();
232ebeed880SDevin Coughlin         CI++;
233ebeed880SDevin Coughlin       }
234ebeed880SDevin Coughlin 
235fd727748STed Kremenek       if (capturedR != originalR) {
236ebeed880SDevin Coughlin         SVal originalV;
237b570195cSAnna Zaks         const LocationContext *LCtx = Pred->getLocationContext();
238ebeed880SDevin Coughlin         if (copyExpr) {
239b570195cSAnna Zaks           originalV = State->getSVal(copyExpr, LCtx);
240ebeed880SDevin Coughlin         } else {
241ebeed880SDevin Coughlin           originalV = State->getSVal(loc::MemRegionVal(originalR));
242ebeed880SDevin Coughlin         }
243b570195cSAnna Zaks         State = State->bindLoc(loc::MemRegionVal(capturedR), originalV, LCtx);
244fd727748STed Kremenek       }
245fd727748STed Kremenek     }
246fd727748STed Kremenek   }
247fd727748STed Kremenek 
248a9ce612fSTed Kremenek   ExplodedNodeSet Tmp;
249d94854a4STed Kremenek   StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
250632e3b7eSTed Kremenek   Bldr.generateNode(BE, Pred,
251fd727748STed Kremenek                     State->BindExpr(BE, Pred->getLocationContext(), V),
2520dbb783cSCraig Topper                     nullptr, ProgramPoint::PostLValueKind);
253a9ce612fSTed Kremenek 
254a9ce612fSTed Kremenek   // FIXME: Move all post/pre visits to ::Visit().
255a9ce612fSTed Kremenek   getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this);
256a9ce612fSTed Kremenek }
257a9ce612fSTed Kremenek 
handleLValueBitCast(ProgramStateRef state,const Expr * Ex,const LocationContext * LCtx,QualType T,QualType ExTy,const CastExpr * CastE,StmtNodeBuilder & Bldr,ExplodedNode * Pred)25864c01f7bSDevin Coughlin ProgramStateRef ExprEngine::handleLValueBitCast(
25964c01f7bSDevin Coughlin     ProgramStateRef state, const Expr* Ex, const LocationContext* LCtx,
26064c01f7bSDevin Coughlin     QualType T, QualType ExTy, const CastExpr* CastE, StmtNodeBuilder& Bldr,
26164c01f7bSDevin Coughlin     ExplodedNode* Pred) {
2622fd6aa7dSArtem Dergachev   if (T->isLValueReferenceType()) {
2632fd6aa7dSArtem Dergachev     assert(!CastE->getType()->isLValueReferenceType());
2642fd6aa7dSArtem Dergachev     ExTy = getContext().getLValueReferenceType(ExTy);
2652fd6aa7dSArtem Dergachev   } else if (T->isRValueReferenceType()) {
2662fd6aa7dSArtem Dergachev     assert(!CastE->getType()->isRValueReferenceType());
2672fd6aa7dSArtem Dergachev     ExTy = getContext().getRValueReferenceType(ExTy);
2682fd6aa7dSArtem Dergachev   }
26964c01f7bSDevin Coughlin   // Delegate to SValBuilder to process.
270468bc0d8SArtem Dergachev   SVal OrigV = state->getSVal(Ex, LCtx);
271468bc0d8SArtem Dergachev   SVal V = svalBuilder.evalCast(OrigV, T, ExTy);
27264c01f7bSDevin Coughlin   // Negate the result if we're treating the boolean as a signed i1
273ee8987d5SBalazs Benics   if (CastE->getCastKind() == CK_BooleanToSignedIntegral && V.isValid())
274ee8987d5SBalazs Benics     V = svalBuilder.evalMinus(V.castAs<NonLoc>());
275ee8987d5SBalazs Benics 
27664c01f7bSDevin Coughlin   state = state->BindExpr(CastE, LCtx, V);
277468bc0d8SArtem Dergachev   if (V.isUnknown() && !OrigV.isUnknown()) {
2785882e6f3SGabor Horvath     state = escapeValues(state, OrigV, PSK_EscapeOther);
279468bc0d8SArtem Dergachev   }
28064c01f7bSDevin Coughlin   Bldr.generateNode(CastE, Pred, state);
28164c01f7bSDevin Coughlin 
28264c01f7bSDevin Coughlin   return state;
28364c01f7bSDevin Coughlin }
28464c01f7bSDevin Coughlin 
VisitCast(const CastExpr * CastE,const Expr * Ex,ExplodedNode * Pred,ExplodedNodeSet & Dst)285a9ce612fSTed Kremenek void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
286a9ce612fSTed Kremenek                            ExplodedNode *Pred, ExplodedNodeSet &Dst) {
287a9ce612fSTed Kremenek 
288a9ce612fSTed Kremenek   ExplodedNodeSet dstPreStmt;
289a9ce612fSTed Kremenek   getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this);
290a9ce612fSTed Kremenek 
291aa454ddaSBalazs Benics   if (CastE->getCastKind() == CK_LValueToRValue ||
292aa454ddaSBalazs Benics       CastE->getCastKind() == CK_LValueToRValueBitCast) {
293a9ce612fSTed Kremenek     for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
294a9ce612fSTed Kremenek          I!=E; ++I) {
295a9ce612fSTed Kremenek       ExplodedNode *subExprNode = *I;
29649b1e38eSTed Kremenek       ProgramStateRef state = subExprNode->getState();
297632e3b7eSTed Kremenek       const LocationContext *LCtx = subExprNode->getLocationContext();
298a85f38baSTed Kremenek       evalLoad(Dst, CastE, CastE, subExprNode, state, state->getSVal(Ex, LCtx));
299a9ce612fSTed Kremenek     }
300a9ce612fSTed Kremenek     return;
301a9ce612fSTed Kremenek   }
302a9ce612fSTed Kremenek 
303a9ce612fSTed Kremenek   // All other casts.
304a9ce612fSTed Kremenek   QualType T = CastE->getType();
305a9ce612fSTed Kremenek   QualType ExTy = Ex->getType();
306a9ce612fSTed Kremenek 
307a9ce612fSTed Kremenek   if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
308a9ce612fSTed Kremenek     T = ExCast->getTypeAsWritten();
309a9ce612fSTed Kremenek 
310d94854a4STed Kremenek   StmtNodeBuilder Bldr(dstPreStmt, Dst, *currBldrCtx);
311a9ce612fSTed Kremenek   for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
312a9ce612fSTed Kremenek        I != E; ++I) {
313a9ce612fSTed Kremenek 
314a9ce612fSTed Kremenek     Pred = *I;
315081af085SJordan Rose     ProgramStateRef state = Pred->getState();
316081af085SJordan Rose     const LocationContext *LCtx = Pred->getLocationContext();
317a9ce612fSTed Kremenek 
318a9ce612fSTed Kremenek     switch (CastE->getCastKind()) {
319a9ce612fSTed Kremenek       case CK_LValueToRValue:
320aa454ddaSBalazs Benics       case CK_LValueToRValueBitCast:
32183d382b1SDavid Blaikie         llvm_unreachable("LValueToRValue casts handled earlier.");
322a9ce612fSTed Kremenek       case CK_ToVoid:
323a9ce612fSTed Kremenek         continue;
324a9ce612fSTed Kremenek         // The analyzer doesn't do anything special with these casts,
325a9ce612fSTed Kremenek         // since it understands retain/release semantics already.
3262d637d2eSJohn McCall       case CK_ARCProduceObject:
3272d637d2eSJohn McCall       case CK_ARCConsumeObject:
3282d637d2eSJohn McCall       case CK_ARCReclaimReturnedObject:
3292d637d2eSJohn McCall       case CK_ARCExtendBlockObject: // Fall-through.
330ed90df38SDouglas Gregor       case CK_CopyAndAutoreleaseBlockObject:
331fa35df62SDavid Chisnall         // The analyser can ignore atomic casts for now, although some future
332fa35df62SDavid Chisnall         // checkers may want to make certain that you're not modifying the same
333fa35df62SDavid Chisnall         // value through atomic and nonatomic pointers.
334fa35df62SDavid Chisnall       case CK_AtomicToNonAtomic:
335fa35df62SDavid Chisnall       case CK_NonAtomicToAtomic:
336a9ce612fSTed Kremenek         // True no-ops.
337a9ce612fSTed Kremenek       case CK_NoOp:
338c9318304SJordan Rose       case CK_ConstructorConversion:
339081af085SJordan Rose       case CK_UserDefinedConversion:
34034866c77SEli Friedman       case CK_FunctionToPointerDecay:
34134866c77SEli Friedman       case CK_BuiltinFnToFnPtr: {
342a9ce612fSTed Kremenek         // Copy the SVal of Ex to CastE.
34349b1e38eSTed Kremenek         ProgramStateRef state = Pred->getState();
344632e3b7eSTed Kremenek         const LocationContext *LCtx = Pred->getLocationContext();
345632e3b7eSTed Kremenek         SVal V = state->getSVal(Ex, LCtx);
346632e3b7eSTed Kremenek         state = state->BindExpr(CastE, LCtx, V);
347e594034fSAnna Zaks         Bldr.generateNode(CastE, Pred, state);
348a9ce612fSTed Kremenek         continue;
349a9ce612fSTed Kremenek       }
350434f1320SJordan Rose       case CK_MemberPointerToBoolean:
35164c01f7bSDevin Coughlin       case CK_PointerToBoolean: {
35264c01f7bSDevin Coughlin         SVal V = state->getSVal(Ex, LCtx);
35364c01f7bSDevin Coughlin         auto PTMSV = V.getAs<nonloc::PointerToMember>();
35464c01f7bSDevin Coughlin         if (PTMSV)
35564c01f7bSDevin Coughlin           V = svalBuilder.makeTruthVal(!PTMSV->isNullMemberPointer(), ExTy);
35664c01f7bSDevin Coughlin         if (V.isUndef() || PTMSV) {
35764c01f7bSDevin Coughlin           state = state->BindExpr(CastE, LCtx, V);
35864c01f7bSDevin Coughlin           Bldr.generateNode(CastE, Pred, state);
35964c01f7bSDevin Coughlin           continue;
36064c01f7bSDevin Coughlin         }
36164c01f7bSDevin Coughlin         // Explicitly proceed with default handler for this case cascade.
36264c01f7bSDevin Coughlin         state =
36364c01f7bSDevin Coughlin             handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred);
36464c01f7bSDevin Coughlin         continue;
36564c01f7bSDevin Coughlin       }
366a9ce612fSTed Kremenek       case CK_Dependent:
367a9ce612fSTed Kremenek       case CK_ArrayToPointerDecay:
368a9ce612fSTed Kremenek       case CK_BitCast:
369e1468322SDavid Tweed       case CK_AddressSpaceConversion:
370df1ed009SGeorge Burgess IV       case CK_BooleanToSignedIntegral:
371a9ce612fSTed Kremenek       case CK_IntegralToPointer:
37264c01f7bSDevin Coughlin       case CK_PointerToIntegral: {
37364c01f7bSDevin Coughlin         SVal V = state->getSVal(Ex, LCtx);
374*96ccb690SBalazs Benics         if (isa<nonloc::PointerToMember>(V)) {
37564c01f7bSDevin Coughlin           state = state->BindExpr(CastE, LCtx, UnknownVal());
37664c01f7bSDevin Coughlin           Bldr.generateNode(CastE, Pred, state);
37764c01f7bSDevin Coughlin           continue;
37864c01f7bSDevin Coughlin         }
37964c01f7bSDevin Coughlin         // Explicitly proceed with default handler for this case cascade.
38064c01f7bSDevin Coughlin         state =
38164c01f7bSDevin Coughlin             handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred);
38264c01f7bSDevin Coughlin         continue;
38364c01f7bSDevin Coughlin       }
384a9ce612fSTed Kremenek       case CK_IntegralToBoolean:
385a9ce612fSTed Kremenek       case CK_IntegralToFloating:
386a9ce612fSTed Kremenek       case CK_FloatingToIntegral:
387a9ce612fSTed Kremenek       case CK_FloatingToBoolean:
388a9ce612fSTed Kremenek       case CK_FloatingCast:
389a9ce612fSTed Kremenek       case CK_FloatingRealToComplex:
390a9ce612fSTed Kremenek       case CK_FloatingComplexToReal:
391a9ce612fSTed Kremenek       case CK_FloatingComplexToBoolean:
392a9ce612fSTed Kremenek       case CK_FloatingComplexCast:
393a9ce612fSTed Kremenek       case CK_FloatingComplexToIntegralComplex:
394a9ce612fSTed Kremenek       case CK_IntegralRealToComplex:
395a9ce612fSTed Kremenek       case CK_IntegralComplexToReal:
396a9ce612fSTed Kremenek       case CK_IntegralComplexToBoolean:
397a9ce612fSTed Kremenek       case CK_IntegralComplexCast:
398a9ce612fSTed Kremenek       case CK_IntegralComplexToFloatingComplex:
3999320b87cSJohn McCall       case CK_CPointerToObjCPointerCast:
4009320b87cSJohn McCall       case CK_BlockPointerToObjCPointerCast:
401a9ce612fSTed Kremenek       case CK_AnyPointerToBlockPointerCast:
4021b4fb3e0SGuy Benyei       case CK_ObjCObjectLValueCast:
403b555b76eSAndrew Savonichev       case CK_ZeroToOCLOpaqueType:
4040bc4b2d3SYaxun Liu       case CK_IntToOCLSampler:
40599bda375SLeonard Chan       case CK_LValueBitCast:
4069fa7f484SBevin Hansson       case CK_FloatingToFixedPoint:
4079fa7f484SBevin Hansson       case CK_FixedPointToFloating:
408b4ba467dSLeonard Chan       case CK_FixedPointCast:
4098f7caae0SLeonard Chan       case CK_FixedPointToBoolean:
4108f7caae0SLeonard Chan       case CK_FixedPointToIntegral:
4118f7caae0SLeonard Chan       case CK_IntegralToFixedPoint: {
41264c01f7bSDevin Coughlin         state =
41364c01f7bSDevin Coughlin             handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred);
414a9ce612fSTed Kremenek         continue;
415a9ce612fSTed Kremenek       }
416e961b445SPierre Gousseau       case CK_IntegralCast: {
417e961b445SPierre Gousseau         // Delegate to SValBuilder to process.
418e961b445SPierre Gousseau         SVal V = state->getSVal(Ex, LCtx);
419d835dd4cSDenys Petrov         if (AMgr.options.ShouldSupportSymbolicIntegerCasts)
420d835dd4cSDenys Petrov           V = svalBuilder.evalCast(V, T, ExTy);
421d835dd4cSDenys Petrov         else
422e961b445SPierre Gousseau           V = svalBuilder.evalIntegralCast(state, V, T, ExTy);
423e961b445SPierre Gousseau         state = state->BindExpr(CastE, LCtx, V);
424e961b445SPierre Gousseau         Bldr.generateNode(CastE, Pred, state);
425e961b445SPierre Gousseau         continue;
426e961b445SPierre Gousseau       }
427a9ce612fSTed Kremenek       case CK_DerivedToBase:
428a9ce612fSTed Kremenek       case CK_UncheckedDerivedToBase: {
429a9ce612fSTed Kremenek         // For DerivedToBase cast, delegate to the store manager.
430632e3b7eSTed Kremenek         SVal val = state->getSVal(Ex, LCtx);
431996d309fSJordan Rose         val = getStoreManager().evalDerivedToBase(val, CastE);
432632e3b7eSTed Kremenek         state = state->BindExpr(CastE, LCtx, val);
433e594034fSAnna Zaks         Bldr.generateNode(CastE, Pred, state);
434a9ce612fSTed Kremenek         continue;
435a9ce612fSTed Kremenek       }
4363bc6809eSAnna Zaks       // Handle C++ dyn_cast.
4373bc6809eSAnna Zaks       case CK_Dynamic: {
4383bc6809eSAnna Zaks         SVal val = state->getSVal(Ex, LCtx);
4393bc6809eSAnna Zaks 
4403bc6809eSAnna Zaks         // Compute the type of the result.
4413bc6809eSAnna Zaks         QualType resultType = CastE->getType();
44294a7b849SAnna Zaks         if (CastE->isGLValue())
4433bc6809eSAnna Zaks           resultType = getContext().getPointerType(resultType);
4443bc6809eSAnna Zaks 
445da8bd972SDenys Petrov         bool Failed = true;
4463bc6809eSAnna Zaks 
447da8bd972SDenys Petrov         // Check if the value being cast does not evaluates to 0.
448da8bd972SDenys Petrov         if (!val.isZeroConstant())
449da8bd972SDenys Petrov           if (Optional<SVal> V =
450da8bd972SDenys Petrov                   StateMgr.getStoreManager().evalBaseToDerived(val, T)) {
451da8bd972SDenys Petrov             val = *V;
452da8bd972SDenys Petrov             Failed = false;
453da8bd972SDenys Petrov           }
4543bc6809eSAnna Zaks 
4553bc6809eSAnna Zaks         if (Failed) {
45602ecae92SAnna Zaks           if (T->isReferenceType()) {
45702ecae92SAnna Zaks             // A bad_cast exception is thrown if input value is a reference.
45802ecae92SAnna Zaks             // Currently, we model this, by generating a sink.
4594b4613cbSJordan Rose             Bldr.generateSink(CastE, Pred, state);
46002ecae92SAnna Zaks             continue;
46102ecae92SAnna Zaks           } else {
462f36a6f54SAnna Zaks             // If the cast fails on a pointer, bind to 0.
46398588841SVince Bridgers             state = state->BindExpr(CastE, LCtx,
46498588841SVince Bridgers                                     svalBuilder.makeNullWithType(resultType));
46502ecae92SAnna Zaks           }
4663bc6809eSAnna Zaks         } else {
4673bc6809eSAnna Zaks           // If we don't know if the cast succeeded, conjure a new symbol.
4683bc6809eSAnna Zaks           if (val.isUnknown()) {
469d227833cSTed Kremenek             DefinedOrUnknownSVal NewSym =
4700dbb783cSCraig Topper               svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType,
471d94854a4STed Kremenek                                            currBldrCtx->blockCount());
4723bc6809eSAnna Zaks             state = state->BindExpr(CastE, LCtx, NewSym);
4733bc6809eSAnna Zaks           } else
4743bc6809eSAnna Zaks             // Else, bind to the derived region value.
4753bc6809eSAnna Zaks             state = state->BindExpr(CastE, LCtx, val);
4763bc6809eSAnna Zaks         }
4773bc6809eSAnna Zaks         Bldr.generateNode(CastE, Pred, state);
4783bc6809eSAnna Zaks         continue;
4793bc6809eSAnna Zaks       }
48044583ce6SGabor Horvath       case CK_BaseToDerived: {
48144583ce6SGabor Horvath         SVal val = state->getSVal(Ex, LCtx);
48244583ce6SGabor Horvath         QualType resultType = CastE->getType();
48344583ce6SGabor Horvath         if (CastE->isGLValue())
48444583ce6SGabor Horvath           resultType = getContext().getPointerType(resultType);
48544583ce6SGabor Horvath 
48644583ce6SGabor Horvath         if (!val.isConstant()) {
487da8bd972SDenys Petrov           Optional<SVal> V = getStoreManager().evalBaseToDerived(val, T);
488da8bd972SDenys Petrov           val = V ? *V : UnknownVal();
48944583ce6SGabor Horvath         }
49044583ce6SGabor Horvath 
49144583ce6SGabor Horvath         // Failed to cast or the result is unknown, fall back to conservative.
492da8bd972SDenys Petrov         if (val.isUnknown()) {
49344583ce6SGabor Horvath           val =
49444583ce6SGabor Horvath             svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType,
49544583ce6SGabor Horvath                                          currBldrCtx->blockCount());
49644583ce6SGabor Horvath         }
49744583ce6SGabor Horvath         state = state->BindExpr(CastE, LCtx, val);
49844583ce6SGabor Horvath         Bldr.generateNode(CastE, Pred, state);
49944583ce6SGabor Horvath         continue;
50044583ce6SGabor Horvath       }
50127252a1fSRichard Smith       case CK_NullToPointer: {
50298588841SVince Bridgers         SVal V = svalBuilder.makeNullWithType(CastE->getType());
50327252a1fSRichard Smith         state = state->BindExpr(CastE, LCtx, V);
50427252a1fSRichard Smith         Bldr.generateNode(CastE, Pred, state);
50527252a1fSRichard Smith         continue;
50627252a1fSRichard Smith       }
507434f1320SJordan Rose       case CK_NullToMemberPointer: {
50864c01f7bSDevin Coughlin         SVal V = svalBuilder.getMemberPointer(nullptr);
509434f1320SJordan Rose         state = state->BindExpr(CastE, LCtx, V);
510434f1320SJordan Rose         Bldr.generateNode(CastE, Pred, state);
511434f1320SJordan Rose         continue;
512434f1320SJordan Rose       }
51364c01f7bSDevin Coughlin       case CK_DerivedToBaseMemberPointer:
51464c01f7bSDevin Coughlin       case CK_BaseToDerivedMemberPointer:
51564c01f7bSDevin Coughlin       case CK_ReinterpretMemberPointer: {
51664c01f7bSDevin Coughlin         SVal V = state->getSVal(Ex, LCtx);
51764c01f7bSDevin Coughlin         if (auto PTMSV = V.getAs<nonloc::PointerToMember>()) {
51821daada9SDeep Majumder           SVal CastedPTMSV =
51921daada9SDeep Majumder               svalBuilder.makePointerToMember(getBasicVals().accumCXXBase(
52021daada9SDeep Majumder                   CastE->path(), *PTMSV, CastE->getCastKind()));
52164c01f7bSDevin Coughlin           state = state->BindExpr(CastE, LCtx, CastedPTMSV);
52264c01f7bSDevin Coughlin           Bldr.generateNode(CastE, Pred, state);
52364c01f7bSDevin Coughlin           continue;
52464c01f7bSDevin Coughlin         }
52564c01f7bSDevin Coughlin         // Explicitly proceed with default handler for this case cascade.
52664c01f7bSDevin Coughlin       }
52755662b24SBalazs Benics         LLVM_FALLTHROUGH;
528a9ce612fSTed Kremenek       // Various C++ casts that are not handled yet.
529a9ce612fSTed Kremenek       case CK_ToUnion:
53055662b24SBalazs Benics       case CK_MatrixCast:
5316477e97aSAnna Zaks       case CK_VectorSplat: {
53255662b24SBalazs Benics         QualType resultType = CastE->getType();
53355662b24SBalazs Benics         if (CastE->isGLValue())
53455662b24SBalazs Benics           resultType = getContext().getPointerType(resultType);
53555662b24SBalazs Benics         SVal result = svalBuilder.conjureSymbolVal(
53655662b24SBalazs Benics             /*symbolTag=*/nullptr, CastE, LCtx, resultType,
53755662b24SBalazs Benics             currBldrCtx->blockCount());
53855662b24SBalazs Benics         state = state->BindExpr(CastE, LCtx, result);
53955662b24SBalazs Benics         Bldr.generateNode(CastE, Pred, state);
54071ab6c98SSaurabh Jha         continue;
54171ab6c98SSaurabh Jha       }
542a9ce612fSTed Kremenek     }
543a9ce612fSTed Kremenek   }
544a9ce612fSTed Kremenek }
545a9ce612fSTed Kremenek 
VisitCompoundLiteralExpr(const CompoundLiteralExpr * CL,ExplodedNode * Pred,ExplodedNodeSet & Dst)546a9ce612fSTed Kremenek void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
547a9ce612fSTed Kremenek                                           ExplodedNode *Pred,
548a9ce612fSTed Kremenek                                           ExplodedNodeSet &Dst) {
549d94854a4STed Kremenek   StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
55052367920SAnna Zaks 
5515d2abefbSJordan Rose   ProgramStateRef State = Pred->getState();
5525d2abefbSJordan Rose   const LocationContext *LCtx = Pred->getLocationContext();
553a9ce612fSTed Kremenek 
5545d2abefbSJordan Rose   const Expr *Init = CL->getInitializer();
5555d2abefbSJordan Rose   SVal V = State->getSVal(CL->getInitializer(), LCtx);
5565d2abefbSJordan Rose 
55716be17adSBalazs Benics   if (isa<CXXConstructExpr, CXXStdInitializerListExpr>(Init)) {
5585d2abefbSJordan Rose     // No work needed. Just pass the value up to this expression.
5595d2abefbSJordan Rose   } else {
5605d2abefbSJordan Rose     assert(isa<InitListExpr>(Init));
5615d2abefbSJordan Rose     Loc CLLoc = State->getLValue(CL, LCtx);
562b570195cSAnna Zaks     State = State->bindLoc(CLLoc, V, LCtx);
563a9ce612fSTed Kremenek 
564b3189a18SRichard Smith     if (CL->isGLValue())
5655d2abefbSJordan Rose       V = CLLoc;
5665d2abefbSJordan Rose   }
5675d2abefbSJordan Rose 
5685d2abefbSJordan Rose   B.generateNode(CL, Pred, State->BindExpr(CL, LCtx, V));
569a9ce612fSTed Kremenek }
570a9ce612fSTed Kremenek 
VisitDeclStmt(const DeclStmt * DS,ExplodedNode * Pred,ExplodedNodeSet & Dst)571a9ce612fSTed Kremenek void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
572a9ce612fSTed Kremenek                                ExplodedNodeSet &Dst) {
573cb1eeb42SBalázs Kéri   if (isa<TypedefNameDecl>(*DS->decl_begin())) {
574cb1eeb42SBalázs Kéri     // C99 6.7.7 "Any array size expressions associated with variable length
575cb1eeb42SBalázs Kéri     // array declarators are evaluated each time the declaration of the typedef
576cb1eeb42SBalázs Kéri     // name is reached in the order of execution."
577cb1eeb42SBalázs Kéri     // The checkers should know about typedef to be able to handle VLA size
578cb1eeb42SBalázs Kéri     // expressions.
579cb1eeb42SBalázs Kéri     ExplodedNodeSet DstPre;
580cb1eeb42SBalázs Kéri     getCheckerManager().runCheckersForPreStmt(DstPre, Pred, DS, *this);
581cb1eeb42SBalázs Kéri     getCheckerManager().runCheckersForPostStmt(Dst, DstPre, DS, *this);
582cb1eeb42SBalázs Kéri     return;
583cb1eeb42SBalázs Kéri   }
584cb1eeb42SBalázs Kéri 
585a9ce612fSTed Kremenek   // Assumption: The CFG has one DeclStmt per Decl.
586907e126bSAnna Zaks   const VarDecl *VD = dyn_cast_or_null<VarDecl>(*DS->decl_begin());
587a9ce612fSTed Kremenek 
588907e126bSAnna Zaks   if (!VD) {
589e594034fSAnna Zaks     //TODO:AZ: remove explicit insertion after refactoring is done.
590e594034fSAnna Zaks     Dst.insert(Pred);
591a9ce612fSTed Kremenek     return;
592e594034fSAnna Zaks   }
593a9ce612fSTed Kremenek 
594a9ce612fSTed Kremenek   // FIXME: all pre/post visits should eventually be handled by ::Visit().
595a9ce612fSTed Kremenek   ExplodedNodeSet dstPreVisit;
596a9ce612fSTed Kremenek   getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this);
597a9ce612fSTed Kremenek 
598cb7b7eafSJordan Rose   ExplodedNodeSet dstEvaluated;
599cb7b7eafSJordan Rose   StmtNodeBuilder B(dstPreVisit, dstEvaluated, *currBldrCtx);
600a9ce612fSTed Kremenek   for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end();
601a9ce612fSTed Kremenek        I!=E; ++I) {
602a9ce612fSTed Kremenek     ExplodedNode *N = *I;
60349b1e38eSTed Kremenek     ProgramStateRef state = N->getState();
604a9ce612fSTed Kremenek     const LocationContext *LC = N->getLocationContext();
605a9ce612fSTed Kremenek 
6067c1f4086SAnna Zaks     // Decls without InitExpr are not initialized explicitly.
607a9ce612fSTed Kremenek     if (const Expr *InitEx = VD->getInit()) {
6087c1f4086SAnna Zaks 
6097c1f4086SAnna Zaks       // Note in the state that the initialization has occurred.
6107c1f4086SAnna Zaks       ExplodedNode *UpdatedN = N;
61120edae87SJordan Rose       SVal InitVal = state->getSVal(InitEx, LC);
612a9ce612fSTed Kremenek 
613412c0af2SDevin Coughlin       assert(DS->isSingleDecl());
6141fe52474SArtem Dergachev       if (getObjectUnderConstruction(state, DS, LC)) {
6151fe52474SArtem Dergachev         state = finishObjectConstruction(state, DS, LC);
616eab627b9SJordan Rose         // We constructed the object directly in the variable.
617eab627b9SJordan Rose         // No need to bind anything.
6187c1f4086SAnna Zaks         B.generateNode(DS, UpdatedN, state);
619eab627b9SJordan Rose       } else {
620a9ce612fSTed Kremenek         // Recover some path-sensitivity if a scalar value evaluated to
621a9ce612fSTed Kremenek         // UnknownVal.
6222d299982SAnna Zaks         if (InitVal.isUnknown()) {
62334ac1cf3STed Kremenek           QualType Ty = InitEx->getType();
62494a7b849SAnna Zaks           if (InitEx->isGLValue()) {
62534ac1cf3STed Kremenek             Ty = getContext().getPointerType(Ty);
62634ac1cf3STed Kremenek           }
62734ac1cf3STed Kremenek 
6280dbb783cSCraig Topper           InitVal = svalBuilder.conjureSymbolVal(nullptr, InitEx, LC, Ty,
629d94854a4STed Kremenek                                                  currBldrCtx->blockCount());
630a9ce612fSTed Kremenek         }
6317c1f4086SAnna Zaks 
6327c1f4086SAnna Zaks 
6337c1f4086SAnna Zaks         B.takeNodes(UpdatedN);
634bfb3520fSAnna Zaks         ExplodedNodeSet Dst2;
6357c1f4086SAnna Zaks         evalBind(Dst2, DS, UpdatedN, state->getLValue(VD, LC), InitVal, true);
636bfb3520fSAnna Zaks         B.addNodes(Dst2);
637a9ce612fSTed Kremenek       }
638eab627b9SJordan Rose     }
639a9ce612fSTed Kremenek     else {
6401afcb744STed Kremenek       B.generateNode(DS, N, state);
641a9ce612fSTed Kremenek     }
642a9ce612fSTed Kremenek   }
643cb7b7eafSJordan Rose 
644cb7b7eafSJordan Rose   getCheckerManager().runCheckersForPostStmt(Dst, B.getResults(), DS, *this);
645a9ce612fSTed Kremenek }
646a9ce612fSTed Kremenek 
VisitLogicalExpr(const BinaryOperator * B,ExplodedNode * Pred,ExplodedNodeSet & Dst)647a9ce612fSTed Kremenek void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
648a9ce612fSTed Kremenek                                   ExplodedNodeSet &Dst) {
64960cde76fSArtem Dergachev   // This method acts upon CFG elements for logical operators && and ||
65060cde76fSArtem Dergachev   // and attaches the value (true or false) to them as expressions.
65160cde76fSArtem Dergachev   // It doesn't produce any state splits.
65260cde76fSArtem Dergachev   // If we made it that far, we're past the point when we modeled the short
65360cde76fSArtem Dergachev   // circuit. It means that we should have precise knowledge about whether
65460cde76fSArtem Dergachev   // we've short-circuited. If we did, we already know the value we need to
65560cde76fSArtem Dergachev   // bind. If we didn't, the value of the RHS (casted to the boolean type)
65660cde76fSArtem Dergachev   // is the answer.
65760cde76fSArtem Dergachev   // Currently this method tries to figure out whether we've short-circuited
65860cde76fSArtem Dergachev   // by looking at the ExplodedGraph. This method is imperfect because there
65960cde76fSArtem Dergachev   // could inevitably have been merges that would have resulted in multiple
66060cde76fSArtem Dergachev   // potential path traversal histories. We bail out when we fail.
66160cde76fSArtem Dergachev   // Due to this ambiguity, a more reliable solution would have been to
66260cde76fSArtem Dergachev   // track the short circuit operation history path-sensitively until
66360cde76fSArtem Dergachev   // we evaluate the respective logical operator.
664a9ce612fSTed Kremenek   assert(B->getOpcode() == BO_LAnd ||
665a9ce612fSTed Kremenek          B->getOpcode() == BO_LOr);
666a9ce612fSTed Kremenek 
667d94854a4STed Kremenek   StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
66849b1e38eSTed Kremenek   ProgramStateRef state = Pred->getState();
669a9ce612fSTed Kremenek 
6705904fba8SArtem Dergachev   if (B->getType()->isVectorType()) {
6715904fba8SArtem Dergachev     // FIXME: We do not model vector arithmetic yet. When adding support for
6725904fba8SArtem Dergachev     // that, note that the CFG-based reasoning below does not apply, because
6735904fba8SArtem Dergachev     // logical operators on vectors are not short-circuit. Currently they are
6745904fba8SArtem Dergachev     // modeled as short-circuit in Clang CFG but this is incorrect.
6755904fba8SArtem Dergachev     // Do not set the value for the expression. It'd be UnknownVal by default.
6765904fba8SArtem Dergachev     Bldr.generateNode(B, Pred, state);
6775904fba8SArtem Dergachev     return;
6785904fba8SArtem Dergachev   }
6795904fba8SArtem Dergachev 
680cf8d2165SAnna Zaks   ExplodedNode *N = Pred;
681cf8d2165SAnna Zaks   while (!N->getLocation().getAs<BlockEntrance>()) {
682cf8d2165SAnna Zaks     ProgramPoint P = N->getLocation();
683cf8d2165SAnna Zaks     assert(P.getAs<PreStmt>()|| P.getAs<PreStmtPurgeDeadSymbols>());
684cf8d2165SAnna Zaks     (void) P;
68560cde76fSArtem Dergachev     if (N->pred_size() != 1) {
68660cde76fSArtem Dergachev       // We failed to track back where we came from.
68760cde76fSArtem Dergachev       Bldr.generateNode(B, Pred, state);
68860cde76fSArtem Dergachev       return;
68960cde76fSArtem Dergachev     }
690cf8d2165SAnna Zaks     N = *N->pred_begin();
691cf8d2165SAnna Zaks   }
69260cde76fSArtem Dergachev 
69360cde76fSArtem Dergachev   if (N->pred_size() != 1) {
69460cde76fSArtem Dergachev     // We failed to track back where we came from.
69560cde76fSArtem Dergachev     Bldr.generateNode(B, Pred, state);
69660cde76fSArtem Dergachev     return;
69760cde76fSArtem Dergachev   }
69860cde76fSArtem Dergachev 
699cf8d2165SAnna Zaks   N = *N->pred_begin();
700cf8d2165SAnna Zaks   BlockEdge BE = N->getLocation().castAs<BlockEdge>();
701cf8d2165SAnna Zaks   SVal X;
702a9ce612fSTed Kremenek 
703cf8d2165SAnna Zaks   // Determine the value of the expression by introspecting how we
704cf8d2165SAnna Zaks   // got this location in the CFG.  This requires looking at the previous
705cf8d2165SAnna Zaks   // block we were in and what kind of control-flow transfer was involved.
706cf8d2165SAnna Zaks   const CFGBlock *SrcBlock = BE.getSrc();
707cf8d2165SAnna Zaks   // The only terminator (if there is one) that makes sense is a logical op.
708cf8d2165SAnna Zaks   CFGTerminator T = SrcBlock->getTerminator();
709cf8d2165SAnna Zaks   if (const BinaryOperator *Term = cast_or_null<BinaryOperator>(T.getStmt())) {
710cf8d2165SAnna Zaks     (void) Term;
711cf8d2165SAnna Zaks     assert(Term->isLogicalOp());
712cf8d2165SAnna Zaks     assert(SrcBlock->succ_size() == 2);
713cf8d2165SAnna Zaks     // Did we take the true or false branch?
714cf8d2165SAnna Zaks     unsigned constant = (*SrcBlock->succ_begin() == BE.getDst()) ? 1 : 0;
715cf8d2165SAnna Zaks     X = svalBuilder.makeIntVal(constant, B->getType());
716cf8d2165SAnna Zaks   }
717cf8d2165SAnna Zaks   else {
718cf8d2165SAnna Zaks     // If there is no terminator, by construction the last statement
719cf8d2165SAnna Zaks     // in SrcBlock is the value of the enclosing expression.
720cf8d2165SAnna Zaks     // However, we still need to constrain that value to be 0 or 1.
721cf8d2165SAnna Zaks     assert(!SrcBlock->empty());
722cf8d2165SAnna Zaks     CFGStmt Elem = SrcBlock->rbegin()->castAs<CFGStmt>();
723cf8d2165SAnna Zaks     const Expr *RHS = cast<Expr>(Elem.getStmt());
724cf8d2165SAnna Zaks     SVal RHSVal = N->getState()->getSVal(RHS, Pred->getLocationContext());
725cf8d2165SAnna Zaks 
726cf8d2165SAnna Zaks     if (RHSVal.isUndef()) {
727cf8d2165SAnna Zaks       X = RHSVal;
728cf8d2165SAnna Zaks     } else {
7295ac37206SAnton Yartsev       // We evaluate "RHSVal != 0" expression which result in 0 if the value is
7305ac37206SAnton Yartsev       // known to be false, 1 if the value is known to be true and a new symbol
7315ac37206SAnton Yartsev       // when the assumption is unknown.
7325ac37206SAnton Yartsev       nonloc::ConcreteInt Zero(getBasicVals().getValue(0, B->getType()));
7335ac37206SAnton Yartsev       X = evalBinOp(N->getState(), BO_NE,
7345ac37206SAnton Yartsev                     svalBuilder.evalCast(RHSVal, B->getType(), RHS->getType()),
7355ac37206SAnton Yartsev                     Zero, B->getType());
736a9ce612fSTed Kremenek     }
737cf8d2165SAnna Zaks   }
738b50e716bSTed Kremenek   Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X));
739a9ce612fSTed Kremenek }
740a9ce612fSTed Kremenek 
VisitInitListExpr(const InitListExpr * IE,ExplodedNode * Pred,ExplodedNodeSet & Dst)741a9ce612fSTed Kremenek void ExprEngine::VisitInitListExpr(const InitListExpr *IE,
742a9ce612fSTed Kremenek                                    ExplodedNode *Pred,
743a9ce612fSTed Kremenek                                    ExplodedNodeSet &Dst) {
744d94854a4STed Kremenek   StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
745a9ce612fSTed Kremenek 
74649b1e38eSTed Kremenek   ProgramStateRef state = Pred->getState();
747632e3b7eSTed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
748a9ce612fSTed Kremenek   QualType T = getContext().getCanonicalType(IE->getType());
749a9ce612fSTed Kremenek   unsigned NumInitElements = IE->getNumInits();
750a9ce612fSTed Kremenek 
751bef9f8aaSArtem Dergachev   if (!IE->isGLValue() && !IE->isTransparent() &&
752d60a41d9SAnna Zaks       (T->isArrayType() || T->isRecordType() || T->isVectorType() ||
753d60a41d9SAnna Zaks        T->isAnyComplexType())) {
754a9ce612fSTed Kremenek     llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList();
755a9ce612fSTed Kremenek 
756a9ce612fSTed Kremenek     // Handle base case where the initializer has no elements.
757a9ce612fSTed Kremenek     // e.g: static int* myArray[] = {};
758a9ce612fSTed Kremenek     if (NumInitElements == 0) {
759a9ce612fSTed Kremenek       SVal V = svalBuilder.makeCompoundVal(T, vals);
760632e3b7eSTed Kremenek       B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V));
761a9ce612fSTed Kremenek       return;
762a9ce612fSTed Kremenek     }
763a9ce612fSTed Kremenek 
76474115602SKazu Hirata     for (const Stmt *S : llvm::reverse(*IE)) {
76574115602SKazu Hirata       SVal V = state->getSVal(cast<Expr>(S), LCtx);
76664c01f7bSDevin Coughlin       vals = getBasicVals().prependSVal(V, vals);
767a9ce612fSTed Kremenek     }
768a9ce612fSTed Kremenek 
769cbdf10beSAnna Zaks     B.generateNode(IE, Pred,
770632e3b7eSTed Kremenek                    state->BindExpr(IE, LCtx,
771632e3b7eSTed Kremenek                                    svalBuilder.makeCompoundVal(T, vals)));
772a9ce612fSTed Kremenek     return;
773a9ce612fSTed Kremenek   }
774a9ce612fSTed Kremenek 
775d60a41d9SAnna Zaks   // Handle scalars: int{5} and int{} and GLvalues.
776d60a41d9SAnna Zaks   // Note, if the InitListExpr is a GLvalue, it means that there is an address
777d60a41d9SAnna Zaks   // representing it, so it must have a single init element.
7785089f3b3SJordan Rose   assert(NumInitElements <= 1);
779a9ce612fSTed Kremenek 
7805089f3b3SJordan Rose   SVal V;
7815089f3b3SJordan Rose   if (NumInitElements == 0)
7825089f3b3SJordan Rose     V = getSValBuilder().makeZeroVal(T);
7835089f3b3SJordan Rose   else
7845089f3b3SJordan Rose     V = state->getSVal(IE->getInit(0), LCtx);
7855089f3b3SJordan Rose 
7865089f3b3SJordan Rose   B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V));
787a9ce612fSTed Kremenek }
788a9ce612fSTed Kremenek 
VisitGuardedExpr(const Expr * Ex,const Expr * L,const Expr * R,ExplodedNode * Pred,ExplodedNodeSet & Dst)789a9ce612fSTed Kremenek void ExprEngine::VisitGuardedExpr(const Expr *Ex,
790a9ce612fSTed Kremenek                                   const Expr *L,
791a9ce612fSTed Kremenek                                   const Expr *R,
792a9ce612fSTed Kremenek                                   ExplodedNode *Pred,
793a9ce612fSTed Kremenek                                   ExplodedNodeSet &Dst) {
7948591aa78SAnna Zaks   assert(L && R);
7958591aa78SAnna Zaks 
796d94854a4STed Kremenek   StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
79749b1e38eSTed Kremenek   ProgramStateRef state = Pred->getState();
798632e3b7eSTed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
7990dbb783cSCraig Topper   const CFGBlock *SrcBlock = nullptr;
800a9ce612fSTed Kremenek 
8018591aa78SAnna Zaks   // Find the predecessor block.
8028591aa78SAnna Zaks   ProgramStateRef SrcState = state;
803313c2ff3STed Kremenek   for (const ExplodedNode *N = Pred ; N ; N = *N->pred_begin()) {
804313c2ff3STed Kremenek     ProgramPoint PP = N->getLocation();
80587396b9bSDavid Blaikie     if (PP.getAs<PreStmtPurgeDeadSymbols>() || PP.getAs<BlockEntrance>()) {
80660c206e0SGeorge Karpenkov       // If the state N has multiple predecessors P, it means that successors
80760c206e0SGeorge Karpenkov       // of P are all equivalent.
80860c206e0SGeorge Karpenkov       // In turn, that means that all nodes at P are equivalent in terms
80960c206e0SGeorge Karpenkov       // of observable behavior at N, and we can follow any of them.
81060c206e0SGeorge Karpenkov       // FIXME: a more robust solution which does not walk up the tree.
811313c2ff3STed Kremenek       continue;
812313c2ff3STed Kremenek     }
81387396b9bSDavid Blaikie     SrcBlock = PP.castAs<BlockEdge>().getSrc();
8148591aa78SAnna Zaks     SrcState = N->getState();
815bb81ffb3STed Kremenek     break;
816bb81ffb3STed Kremenek   }
817313c2ff3STed Kremenek 
818d03d99daSJordan Rose   assert(SrcBlock && "missing function entry");
819d03d99daSJordan Rose 
820313c2ff3STed Kremenek   // Find the last expression in the predecessor block.  That is the
821313c2ff3STed Kremenek   // expression that is used for the value of the ternary expression.
822313c2ff3STed Kremenek   bool hasValue = false;
823313c2ff3STed Kremenek   SVal V;
824313c2ff3STed Kremenek 
82557d3f145SPete Cooper   for (CFGElement CE : llvm::reverse(*SrcBlock)) {
82600be69abSDavid Blaikie     if (Optional<CFGStmt> CS = CE.getAs<CFGStmt>()) {
82700be69abSDavid Blaikie       const Expr *ValEx = cast<Expr>(CS->getStmt());
8288591aa78SAnna Zaks       ValEx = ValEx->IgnoreParens();
8298591aa78SAnna Zaks 
8308591aa78SAnna Zaks       // For GNU extension '?:' operator, the left hand side will be an
8318591aa78SAnna Zaks       // OpaqueValueExpr, so get the underlying expression.
8328591aa78SAnna Zaks       if (const OpaqueValueExpr *OpaqueEx = dyn_cast<OpaqueValueExpr>(L))
8338591aa78SAnna Zaks         L = OpaqueEx->getSourceExpr();
8348591aa78SAnna Zaks 
8358591aa78SAnna Zaks       // If the last expression in the predecessor block matches true or false
8368591aa78SAnna Zaks       // subexpression, get its the value.
8378591aa78SAnna Zaks       if (ValEx == L->IgnoreParens() || ValEx == R->IgnoreParens()) {
838313c2ff3STed Kremenek         hasValue = true;
8398591aa78SAnna Zaks         V = SrcState->getSVal(ValEx, LCtx);
8408591aa78SAnna Zaks       }
841313c2ff3STed Kremenek       break;
842bb81ffb3STed Kremenek     }
843313c2ff3STed Kremenek   }
844313c2ff3STed Kremenek 
8458591aa78SAnna Zaks   if (!hasValue)
8460dbb783cSCraig Topper     V = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
8470dbb783cSCraig Topper                                      currBldrCtx->blockCount());
848bb81ffb3STed Kremenek 
849bb81ffb3STed Kremenek   // Generate a new node with the binding from the appropriate path.
850bb81ffb3STed Kremenek   B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true));
851a9ce612fSTed Kremenek }
852a9ce612fSTed Kremenek 
853a9ce612fSTed Kremenek void ExprEngine::
VisitOffsetOfExpr(const OffsetOfExpr * OOE,ExplodedNode * Pred,ExplodedNodeSet & Dst)854a9ce612fSTed Kremenek VisitOffsetOfExpr(const OffsetOfExpr *OOE,
855a9ce612fSTed Kremenek                   ExplodedNode *Pred, ExplodedNodeSet &Dst) {
856d94854a4STed Kremenek   StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
857407659abSFangrui Song   Expr::EvalResult Result;
858407659abSFangrui Song   if (OOE->EvaluateAsInt(Result, getContext())) {
859407659abSFangrui Song     APSInt IV = Result.Val.getInt();
860a9ce612fSTed Kremenek     assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType()));
861630f7dafSArtem Dergachev     assert(OOE->getType()->castAs<BuiltinType>()->isInteger());
86261e221f6SJordan Rose     assert(IV.isSigned() == OOE->getType()->isSignedIntegerType());
863a9ce612fSTed Kremenek     SVal X = svalBuilder.makeIntVal(IV);
864632e3b7eSTed Kremenek     B.generateNode(OOE, Pred,
865632e3b7eSTed Kremenek                    Pred->getState()->BindExpr(OOE, Pred->getLocationContext(),
866632e3b7eSTed Kremenek                                               X));
867a9ce612fSTed Kremenek   }
868a9ce612fSTed Kremenek   // FIXME: Handle the case where __builtin_offsetof is not a constant.
869a9ce612fSTed Kremenek }
870a9ce612fSTed Kremenek 
871a9ce612fSTed Kremenek 
872a9ce612fSTed Kremenek void ExprEngine::
VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr * Ex,ExplodedNode * Pred,ExplodedNodeSet & Dst)873a9ce612fSTed Kremenek VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
874a9ce612fSTed Kremenek                               ExplodedNode *Pred,
875a9ce612fSTed Kremenek                               ExplodedNodeSet &Dst) {
8766d03fdb6SJordan Rose   // FIXME: Prechecks eventually go in ::Visit().
8776d03fdb6SJordan Rose   ExplodedNodeSet CheckedSet;
8786d03fdb6SJordan Rose   getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, Ex, *this);
8796d03fdb6SJordan Rose 
8806d03fdb6SJordan Rose   ExplodedNodeSet EvalSet;
8816d03fdb6SJordan Rose   StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx);
882a9ce612fSTed Kremenek 
883a9ce612fSTed Kremenek   QualType T = Ex->getTypeOfArgument();
884a9ce612fSTed Kremenek 
8856d03fdb6SJordan Rose   for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
8866d03fdb6SJordan Rose        I != E; ++I) {
887a9ce612fSTed Kremenek     if (Ex->getKind() == UETT_SizeOf) {
888a9ce612fSTed Kremenek       if (!T->isIncompleteType() && !T->isConstantSizeType()) {
889a9ce612fSTed Kremenek         assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
890a9ce612fSTed Kremenek 
891ee9848e2STed Kremenek         // FIXME: Add support for VLA type arguments and VLA expressions.
892a9ce612fSTed Kremenek         // When that happens, we should probably refactor VLASizeChecker's code.
8936d03fdb6SJordan Rose         continue;
8946d03fdb6SJordan Rose       } else if (T->getAs<ObjCObjectType>()) {
895a9ce612fSTed Kremenek         // Some code tries to take the sizeof an ObjCObjectType, relying that
896a9ce612fSTed Kremenek         // the compiler has laid out its representation.  Just report Unknown
897a9ce612fSTed Kremenek         // for these.
8986d03fdb6SJordan Rose         continue;
899a9ce612fSTed Kremenek       }
900a9ce612fSTed Kremenek     }
901a9ce612fSTed Kremenek 
9025fab0c9eSRichard Smith     APSInt Value = Ex->EvaluateKnownConstInt(getContext());
9035fab0c9eSRichard Smith     CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue());
904a9ce612fSTed Kremenek 
9056d03fdb6SJordan Rose     ProgramStateRef state = (*I)->getState();
9066d03fdb6SJordan Rose     state = state->BindExpr(Ex, (*I)->getLocationContext(),
907632e3b7eSTed Kremenek                             svalBuilder.makeIntVal(amt.getQuantity(),
908a9ce612fSTed Kremenek                                                    Ex->getType()));
9096d03fdb6SJordan Rose     Bldr.generateNode(Ex, *I, state);
9106d03fdb6SJordan Rose   }
9116d03fdb6SJordan Rose 
9126d03fdb6SJordan Rose   getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this);
913a9ce612fSTed Kremenek }
914a9ce612fSTed Kremenek 
handleUOExtension(ExplodedNodeSet::iterator I,const UnaryOperator * U,StmtNodeBuilder & Bldr)91564c01f7bSDevin Coughlin void ExprEngine::handleUOExtension(ExplodedNodeSet::iterator I,
91664c01f7bSDevin Coughlin                                    const UnaryOperator *U,
91764c01f7bSDevin Coughlin                                    StmtNodeBuilder &Bldr) {
91864c01f7bSDevin Coughlin   // FIXME: We can probably just have some magic in Environment::getSVal()
91964c01f7bSDevin Coughlin   // that propagates values, instead of creating a new node here.
92064c01f7bSDevin Coughlin   //
92164c01f7bSDevin Coughlin   // Unary "+" is a no-op, similar to a parentheses.  We still have places
92264c01f7bSDevin Coughlin   // where it may be a block-level expression, so we need to
92364c01f7bSDevin Coughlin   // generate an extra node that just propagates the value of the
92464c01f7bSDevin Coughlin   // subexpression.
92564c01f7bSDevin Coughlin   const Expr *Ex = U->getSubExpr()->IgnoreParens();
92664c01f7bSDevin Coughlin   ProgramStateRef state = (*I)->getState();
92764c01f7bSDevin Coughlin   const LocationContext *LCtx = (*I)->getLocationContext();
92864c01f7bSDevin Coughlin   Bldr.generateNode(U, *I, state->BindExpr(U, LCtx,
92964c01f7bSDevin Coughlin                                            state->getSVal(Ex, LCtx)));
93064c01f7bSDevin Coughlin }
93164c01f7bSDevin Coughlin 
VisitUnaryOperator(const UnaryOperator * U,ExplodedNode * Pred,ExplodedNodeSet & Dst)93264c01f7bSDevin Coughlin void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred,
933a9ce612fSTed Kremenek                                     ExplodedNodeSet &Dst) {
934a63d1dbdSJordan Rose   // FIXME: Prechecks eventually go in ::Visit().
935a63d1dbdSJordan Rose   ExplodedNodeSet CheckedSet;
936a63d1dbdSJordan Rose   getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, U, *this);
937a63d1dbdSJordan Rose 
938a63d1dbdSJordan Rose   ExplodedNodeSet EvalSet;
939a63d1dbdSJordan Rose   StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx);
940a63d1dbdSJordan Rose 
941a63d1dbdSJordan Rose   for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
942a63d1dbdSJordan Rose        I != E; ++I) {
943a9ce612fSTed Kremenek     switch (U->getOpcode()) {
944e594034fSAnna Zaks     default: {
945a63d1dbdSJordan Rose       Bldr.takeNodes(*I);
946e594034fSAnna Zaks       ExplodedNodeSet Tmp;
947a63d1dbdSJordan Rose       VisitIncrementDecrementOperator(U, *I, Tmp);
948e594034fSAnna Zaks       Bldr.addNodes(Tmp);
949a9ce612fSTed Kremenek       break;
950a63d1dbdSJordan Rose     }
951a9ce612fSTed Kremenek     case UO_Real: {
952a9ce612fSTed Kremenek       const Expr *Ex = U->getSubExpr()->IgnoreParens();
953a9ce612fSTed Kremenek 
954a9ce612fSTed Kremenek       // FIXME: We don't have complex SValues yet.
955a9ce612fSTed Kremenek       if (Ex->getType()->isAnyComplexType()) {
956a9ce612fSTed Kremenek         // Just report "Unknown."
957b5d87d88STed Kremenek         break;
958a9ce612fSTed Kremenek       }
959a9ce612fSTed Kremenek 
960a9ce612fSTed Kremenek       // For all other types, UO_Real is an identity operation.
961a9ce612fSTed Kremenek       assert (U->getType() == Ex->getType());
962a63d1dbdSJordan Rose       ProgramStateRef state = (*I)->getState();
963a63d1dbdSJordan Rose       const LocationContext *LCtx = (*I)->getLocationContext();
964a63d1dbdSJordan Rose       Bldr.generateNode(U, *I, state->BindExpr(U, LCtx,
965632e3b7eSTed Kremenek                                                state->getSVal(Ex, LCtx)));
966f011a4a6SAnna Zaks       break;
967a9ce612fSTed Kremenek     }
968a9ce612fSTed Kremenek 
969a9ce612fSTed Kremenek     case UO_Imag: {
970a9ce612fSTed Kremenek       const Expr *Ex = U->getSubExpr()->IgnoreParens();
971a9ce612fSTed Kremenek       // FIXME: We don't have complex SValues yet.
972a9ce612fSTed Kremenek       if (Ex->getType()->isAnyComplexType()) {
973a9ce612fSTed Kremenek         // Just report "Unknown."
974c14557fbSTed Kremenek         break;
975a9ce612fSTed Kremenek       }
976a9ce612fSTed Kremenek       // For all other types, UO_Imag returns 0.
977a63d1dbdSJordan Rose       ProgramStateRef state = (*I)->getState();
978a63d1dbdSJordan Rose       const LocationContext *LCtx = (*I)->getLocationContext();
979a9ce612fSTed Kremenek       SVal X = svalBuilder.makeZeroVal(Ex->getType());
980a63d1dbdSJordan Rose       Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, X));
981f011a4a6SAnna Zaks       break;
982a9ce612fSTed Kremenek     }
983a9ce612fSTed Kremenek 
98464c01f7bSDevin Coughlin     case UO_AddrOf: {
98564c01f7bSDevin Coughlin       // Process pointer-to-member address operation.
98664c01f7bSDevin Coughlin       const Expr *Ex = U->getSubExpr()->IgnoreParens();
98764c01f7bSDevin Coughlin       if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Ex)) {
98864c01f7bSDevin Coughlin         const ValueDecl *VD = DRE->getDecl();
98964c01f7bSDevin Coughlin 
99016be17adSBalazs Benics         if (isa<CXXMethodDecl, FieldDecl, IndirectFieldDecl>(VD)) {
99164c01f7bSDevin Coughlin           ProgramStateRef State = (*I)->getState();
99264c01f7bSDevin Coughlin           const LocationContext *LCtx = (*I)->getLocationContext();
9939cbfdde2SValeriy Savchenko           SVal SV = svalBuilder.getMemberPointer(cast<NamedDecl>(VD));
99464c01f7bSDevin Coughlin           Bldr.generateNode(U, *I, State->BindExpr(U, LCtx, SV));
99564c01f7bSDevin Coughlin           break;
99664c01f7bSDevin Coughlin         }
99764c01f7bSDevin Coughlin       }
99864c01f7bSDevin Coughlin       // Explicitly proceed with default handler for this case cascade.
99964c01f7bSDevin Coughlin       handleUOExtension(I, U, Bldr);
100064c01f7bSDevin Coughlin       break;
100164c01f7bSDevin Coughlin     }
1002a9ce612fSTed Kremenek     case UO_Plus:
100394a7b849SAnna Zaks       assert(!U->isGLValue());
10044dc0b1acSReid Kleckner       LLVM_FALLTHROUGH;
1005a9ce612fSTed Kremenek     case UO_Deref:
1006a9ce612fSTed Kremenek     case UO_Extension: {
100764c01f7bSDevin Coughlin       handleUOExtension(I, U, Bldr);
1008f011a4a6SAnna Zaks       break;
1009a9ce612fSTed Kremenek     }
1010a9ce612fSTed Kremenek 
1011a9ce612fSTed Kremenek     case UO_LNot:
1012a9ce612fSTed Kremenek     case UO_Minus:
1013a9ce612fSTed Kremenek     case UO_Not: {
101494a7b849SAnna Zaks       assert (!U->isGLValue());
1015a9ce612fSTed Kremenek       const Expr *Ex = U->getSubExpr()->IgnoreParens();
1016a63d1dbdSJordan Rose       ProgramStateRef state = (*I)->getState();
1017a63d1dbdSJordan Rose       const LocationContext *LCtx = (*I)->getLocationContext();
1018a9ce612fSTed Kremenek 
1019a9ce612fSTed Kremenek       // Get the value of the subexpression.
1020632e3b7eSTed Kremenek       SVal V = state->getSVal(Ex, LCtx);
1021a9ce612fSTed Kremenek 
1022a9ce612fSTed Kremenek       if (V.isUnknownOrUndef()) {
1023a63d1dbdSJordan Rose         Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, V));
102489dbd3baSTed Kremenek         break;
1025a9ce612fSTed Kremenek       }
1026a9ce612fSTed Kremenek 
1027a9ce612fSTed Kremenek       switch (U->getOpcode()) {
1028a9ce612fSTed Kremenek         default:
102983d382b1SDavid Blaikie           llvm_unreachable("Invalid Opcode.");
1030a9ce612fSTed Kremenek         case UO_Not:
1031a9ce612fSTed Kremenek           // FIXME: Do we need to handle promotions?
10327a2d6deaSBalazs Benics           state = state->BindExpr(
10337a2d6deaSBalazs Benics               U, LCtx, svalBuilder.evalComplement(V.castAs<NonLoc>()));
1034a9ce612fSTed Kremenek           break;
1035a9ce612fSTed Kremenek         case UO_Minus:
1036a9ce612fSTed Kremenek           // FIXME: Do we need to handle promotions?
1037ee8987d5SBalazs Benics           state = state->BindExpr(U, LCtx,
1038ee8987d5SBalazs Benics                                   svalBuilder.evalMinus(V.castAs<NonLoc>()));
1039a9ce612fSTed Kremenek           break;
1040a9ce612fSTed Kremenek         case UO_LNot:
1041a9ce612fSTed Kremenek           // C99 6.5.3.3: "The expression !E is equivalent to (0==E)."
1042a9ce612fSTed Kremenek           //
1043a9ce612fSTed Kremenek           //  Note: technically we do "E == 0", but this is the same in the
1044a9ce612fSTed Kremenek           //    transfer functions as "0 == E".
1045a9ce612fSTed Kremenek           SVal Result;
104605785d16SDavid Blaikie           if (Optional<Loc> LV = V.getAs<Loc>()) {
10479c6e8489SDaniel Marjamaki             Loc X = svalBuilder.makeNullWithType(Ex->getType());
10482fdacbc5SDavid Blaikie             Result = evalBinOp(state, BO_EQ, *LV, X, U->getType());
10499c6e8489SDaniel Marjamaki           } else if (Ex->getType()->isFloatingType()) {
10504e9a2dbdSTed Kremenek             // FIXME: handle floating point types.
10514e9a2dbdSTed Kremenek             Result = UnknownVal();
10524e9a2dbdSTed Kremenek           } else {
1053a9ce612fSTed Kremenek             nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));
10542fdacbc5SDavid Blaikie             Result = evalBinOp(state, BO_EQ, V.castAs<NonLoc>(), X,
1055a9ce612fSTed Kremenek                                U->getType());
1056a9ce612fSTed Kremenek           }
1057a9ce612fSTed Kremenek 
1058632e3b7eSTed Kremenek           state = state->BindExpr(U, LCtx, Result);
1059a9ce612fSTed Kremenek           break;
1060a9ce612fSTed Kremenek       }
1061a63d1dbdSJordan Rose       Bldr.generateNode(U, *I, state);
1062f011a4a6SAnna Zaks       break;
1063a9ce612fSTed Kremenek     }
1064a9ce612fSTed Kremenek     }
1065a63d1dbdSJordan Rose   }
1066a9ce612fSTed Kremenek 
1067a63d1dbdSJordan Rose   getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, U, *this);
1068f011a4a6SAnna Zaks }
1069f011a4a6SAnna Zaks 
VisitIncrementDecrementOperator(const UnaryOperator * U,ExplodedNode * Pred,ExplodedNodeSet & Dst)1070f011a4a6SAnna Zaks void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
1071f011a4a6SAnna Zaks                                                  ExplodedNode *Pred,
1072f011a4a6SAnna Zaks                                                  ExplodedNodeSet &Dst) {
1073a9ce612fSTed Kremenek   // Handle ++ and -- (both pre- and post-increment).
1074a9ce612fSTed Kremenek   assert (U->isIncrementDecrementOp());
1075a9ce612fSTed Kremenek   const Expr *Ex = U->getSubExpr()->IgnoreParens();
1076a9ce612fSTed Kremenek 
107776978f9dSTed Kremenek   const LocationContext *LCtx = Pred->getLocationContext();
107876978f9dSTed Kremenek   ProgramStateRef state = Pred->getState();
1079632e3b7eSTed Kremenek   SVal loc = state->getSVal(Ex, LCtx);
1080a9ce612fSTed Kremenek 
1081a9ce612fSTed Kremenek   // Perform a load.
108276978f9dSTed Kremenek   ExplodedNodeSet Tmp;
1083a85f38baSTed Kremenek   evalLoad(Tmp, U, Ex, Pred, state, loc);
1084a9ce612fSTed Kremenek 
1085e594034fSAnna Zaks   ExplodedNodeSet Dst2;
1086d94854a4STed Kremenek   StmtNodeBuilder Bldr(Tmp, Dst2, *currBldrCtx);
108776978f9dSTed Kremenek   for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end();I!=E;++I) {
1088a9ce612fSTed Kremenek 
108976978f9dSTed Kremenek     state = (*I)->getState();
109076978f9dSTed Kremenek     assert(LCtx == (*I)->getLocationContext());
1091632e3b7eSTed Kremenek     SVal V2_untested = state->getSVal(Ex, LCtx);
1092a9ce612fSTed Kremenek 
1093a9ce612fSTed Kremenek     // Propagate unknown and undefined values.
1094a9ce612fSTed Kremenek     if (V2_untested.isUnknownOrUndef()) {
109588b56caaSRoman Lebedev       state = state->BindExpr(U, LCtx, V2_untested);
109688b56caaSRoman Lebedev 
109788b56caaSRoman Lebedev       // Perform the store, so that the uninitialized value detection happens.
109888b56caaSRoman Lebedev       Bldr.takeNodes(*I);
109988b56caaSRoman Lebedev       ExplodedNodeSet Dst3;
1100cc19f921SRafael Stahl       evalStore(Dst3, U, Ex, *I, state, loc, V2_untested);
110188b56caaSRoman Lebedev       Bldr.addNodes(Dst3);
110288b56caaSRoman Lebedev 
1103a9ce612fSTed Kremenek       continue;
1104a9ce612fSTed Kremenek     }
11052fdacbc5SDavid Blaikie     DefinedSVal V2 = V2_untested.castAs<DefinedSVal>();
1106a9ce612fSTed Kremenek 
1107a9ce612fSTed Kremenek     // Handle all other values.
110876978f9dSTed Kremenek     BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add : BO_Sub;
1109a9ce612fSTed Kremenek 
1110a9ce612fSTed Kremenek     // If the UnaryOperator has non-location type, use its type to create the
1111a9ce612fSTed Kremenek     // constant value. If the UnaryOperator has location type, create the
1112a9ce612fSTed Kremenek     // constant with int type and pointer width.
1113a9ce612fSTed Kremenek     SVal RHS;
1114e47b89d1SHenry Wong     SVal Result;
1115a9ce612fSTed Kremenek 
1116a9ce612fSTed Kremenek     if (U->getType()->isAnyPointerType())
1117a9ce612fSTed Kremenek       RHS = svalBuilder.makeArrayIndex(1);
1118a44ad1b3SJordan Rose     else if (U->getType()->isIntegralOrEnumerationType())
1119a9ce612fSTed Kremenek       RHS = svalBuilder.makeIntVal(1, U->getType());
1120a44ad1b3SJordan Rose     else
1121a44ad1b3SJordan Rose       RHS = UnknownVal();
1122a9ce612fSTed Kremenek 
1123e47b89d1SHenry Wong     // The use of an operand of type bool with the ++ operators is deprecated
1124e47b89d1SHenry Wong     // but valid until C++17. And if the operand of the ++ operator is of type
1125e47b89d1SHenry Wong     // bool, it is set to true until C++17. Note that for '_Bool', it is also
1126e47b89d1SHenry Wong     // set to true when it encounters ++ operator.
1127e47b89d1SHenry Wong     if (U->getType()->isBooleanType() && U->isIncrementOp())
1128e47b89d1SHenry Wong       Result = svalBuilder.makeTruthVal(true, U->getType());
1129e47b89d1SHenry Wong     else
1130e47b89d1SHenry Wong       Result = evalBinOp(state, Op, V2, RHS, U->getType());
1131a9ce612fSTed Kremenek 
1132a9ce612fSTed Kremenek     // Conjure a new symbol if necessary to recover precision.
1133a636fbe7SAnna Zaks     if (Result.isUnknown()){
1134a9ce612fSTed Kremenek       DefinedOrUnknownSVal SymVal =
11357333a9eaSArtem Dergachev         svalBuilder.conjureSymbolVal(nullptr, U, LCtx,
11360dbb783cSCraig Topper                                      currBldrCtx->blockCount());
1137a9ce612fSTed Kremenek       Result = SymVal;
1138a9ce612fSTed Kremenek 
1139a9ce612fSTed Kremenek       // If the value is a location, ++/-- should always preserve
1140a9ce612fSTed Kremenek       // non-nullness.  Check if the original value was non-null, and if so
1141a9ce612fSTed Kremenek       // propagate that constraint.
1142a9ce612fSTed Kremenek       if (Loc::isLocType(U->getType())) {
1143a9ce612fSTed Kremenek         DefinedOrUnknownSVal Constraint =
1144a9ce612fSTed Kremenek         svalBuilder.evalEQ(state, V2,svalBuilder.makeZeroVal(U->getType()));
1145a9ce612fSTed Kremenek 
1146a9ce612fSTed Kremenek         if (!state->assume(Constraint, true)) {
1147a9ce612fSTed Kremenek           // It isn't feasible for the original value to be null.
1148a9ce612fSTed Kremenek           // Propagate this constraint.
1149a9ce612fSTed Kremenek           Constraint = svalBuilder.evalEQ(state, SymVal,
1150a9ce612fSTed Kremenek                                        svalBuilder.makeZeroVal(U->getType()));
1151a9ce612fSTed Kremenek 
1152a9ce612fSTed Kremenek           state = state->assume(Constraint, false);
1153a9ce612fSTed Kremenek           assert(state);
1154a9ce612fSTed Kremenek         }
1155a9ce612fSTed Kremenek       }
1156a9ce612fSTed Kremenek     }
1157a9ce612fSTed Kremenek 
1158a9ce612fSTed Kremenek     // Since the lvalue-to-rvalue conversion is explicit in the AST,
1159a9ce612fSTed Kremenek     // we bind an l-value if the operator is prefix and an lvalue (in C++).
116094a7b849SAnna Zaks     if (U->isGLValue())
1161632e3b7eSTed Kremenek       state = state->BindExpr(U, LCtx, loc);
1162a9ce612fSTed Kremenek     else
1163632e3b7eSTed Kremenek       state = state->BindExpr(U, LCtx, U->isPostfix() ? V2 : Result);
1164a9ce612fSTed Kremenek 
1165a9ce612fSTed Kremenek     // Perform the store.
116676978f9dSTed Kremenek     Bldr.takeNodes(*I);
116776978f9dSTed Kremenek     ExplodedNodeSet Dst3;
1168cc19f921SRafael Stahl     evalStore(Dst3, U, Ex, *I, state, loc, Result);
116976978f9dSTed Kremenek     Bldr.addNodes(Dst3);
1170a9ce612fSTed Kremenek   }
1171e594034fSAnna Zaks   Dst.insert(Dst2);
1172a9ce612fSTed Kremenek }
1173