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