xref: /openbsd-src/gnu/llvm/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===- SValBuilder.cpp - Basic class for all SValBuilder implementations --===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick //  This file defines SValBuilder, the base class for all (complete) SValBuilder
10e5dd7070Spatrick //  implementations.
11e5dd7070Spatrick //
12e5dd7070Spatrick //===----------------------------------------------------------------------===//
13e5dd7070Spatrick 
14e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
15e5dd7070Spatrick #include "clang/AST/ASTContext.h"
16e5dd7070Spatrick #include "clang/AST/Decl.h"
17e5dd7070Spatrick #include "clang/AST/DeclCXX.h"
18e5dd7070Spatrick #include "clang/AST/ExprCXX.h"
19e5dd7070Spatrick #include "clang/AST/ExprObjC.h"
20e5dd7070Spatrick #include "clang/AST/Stmt.h"
21e5dd7070Spatrick #include "clang/AST/Type.h"
22e5dd7070Spatrick #include "clang/Analysis/AnalysisDeclContext.h"
23*12c85518Srobert #include "clang/Basic/LLVM.h"
24e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
25*12c85518Srobert #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
26e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
27ec727ea7Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
28e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
29e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
30e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
31*12c85518Srobert #include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
32e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
33e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
34e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
35e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
36e5dd7070Spatrick #include "llvm/ADT/APSInt.h"
37e5dd7070Spatrick #include "llvm/Support/Casting.h"
38e5dd7070Spatrick #include "llvm/Support/Compiler.h"
39e5dd7070Spatrick #include <cassert>
40*12c85518Srobert #include <optional>
41e5dd7070Spatrick #include <tuple>
42e5dd7070Spatrick 
43e5dd7070Spatrick using namespace clang;
44e5dd7070Spatrick using namespace ento;
45e5dd7070Spatrick 
46e5dd7070Spatrick //===----------------------------------------------------------------------===//
47e5dd7070Spatrick // Basic SVal creation.
48e5dd7070Spatrick //===----------------------------------------------------------------------===//
49e5dd7070Spatrick 
anchor()50e5dd7070Spatrick void SValBuilder::anchor() {}
51e5dd7070Spatrick 
SValBuilder(llvm::BumpPtrAllocator & alloc,ASTContext & context,ProgramStateManager & stateMgr)52*12c85518Srobert SValBuilder::SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
53*12c85518Srobert                          ProgramStateManager &stateMgr)
54*12c85518Srobert     : Context(context), BasicVals(context, alloc),
55*12c85518Srobert       SymMgr(context, BasicVals, alloc), MemMgr(context, alloc),
56*12c85518Srobert       StateMgr(stateMgr),
57*12c85518Srobert       AnOpts(
58*12c85518Srobert           stateMgr.getOwningEngine().getAnalysisManager().getAnalyzerOptions()),
59*12c85518Srobert       ArrayIndexTy(context.LongLongTy),
60*12c85518Srobert       ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) {}
61*12c85518Srobert 
makeZeroVal(QualType type)62e5dd7070Spatrick DefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType type) {
63e5dd7070Spatrick   if (Loc::isLocType(type))
64*12c85518Srobert     return makeNullWithType(type);
65e5dd7070Spatrick 
66e5dd7070Spatrick   if (type->isIntegralOrEnumerationType())
67e5dd7070Spatrick     return makeIntVal(0, type);
68e5dd7070Spatrick 
69e5dd7070Spatrick   if (type->isArrayType() || type->isRecordType() || type->isVectorType() ||
70e5dd7070Spatrick       type->isAnyComplexType())
71e5dd7070Spatrick     return makeCompoundVal(type, BasicVals.getEmptySValList());
72e5dd7070Spatrick 
73e5dd7070Spatrick   // FIXME: Handle floats.
74e5dd7070Spatrick   return UnknownVal();
75e5dd7070Spatrick }
76e5dd7070Spatrick 
makeNonLoc(const SymExpr * lhs,BinaryOperator::Opcode op,const llvm::APSInt & rhs,QualType type)77*12c85518Srobert nonloc::SymbolVal SValBuilder::makeNonLoc(const SymExpr *lhs,
78*12c85518Srobert                                           BinaryOperator::Opcode op,
79*12c85518Srobert                                           const llvm::APSInt &rhs,
80*12c85518Srobert                                           QualType type) {
81e5dd7070Spatrick   // The Environment ensures we always get a persistent APSInt in
82e5dd7070Spatrick   // BasicValueFactory, so we don't need to get the APSInt from
83e5dd7070Spatrick   // BasicValueFactory again.
84e5dd7070Spatrick   assert(lhs);
85e5dd7070Spatrick   assert(!Loc::isLocType(type));
86e5dd7070Spatrick   return nonloc::SymbolVal(SymMgr.getSymIntExpr(lhs, op, rhs, type));
87e5dd7070Spatrick }
88e5dd7070Spatrick 
makeNonLoc(const llvm::APSInt & lhs,BinaryOperator::Opcode op,const SymExpr * rhs,QualType type)89*12c85518Srobert nonloc::SymbolVal SValBuilder::makeNonLoc(const llvm::APSInt &lhs,
90*12c85518Srobert                                           BinaryOperator::Opcode op,
91*12c85518Srobert                                           const SymExpr *rhs, QualType type) {
92e5dd7070Spatrick   assert(rhs);
93e5dd7070Spatrick   assert(!Loc::isLocType(type));
94e5dd7070Spatrick   return nonloc::SymbolVal(SymMgr.getIntSymExpr(lhs, op, rhs, type));
95e5dd7070Spatrick }
96e5dd7070Spatrick 
makeNonLoc(const SymExpr * lhs,BinaryOperator::Opcode op,const SymExpr * rhs,QualType type)97*12c85518Srobert nonloc::SymbolVal SValBuilder::makeNonLoc(const SymExpr *lhs,
98*12c85518Srobert                                           BinaryOperator::Opcode op,
99e5dd7070Spatrick                                           const SymExpr *rhs, QualType type) {
100e5dd7070Spatrick   assert(lhs && rhs);
101e5dd7070Spatrick   assert(!Loc::isLocType(type));
102e5dd7070Spatrick   return nonloc::SymbolVal(SymMgr.getSymSymExpr(lhs, op, rhs, type));
103e5dd7070Spatrick }
104e5dd7070Spatrick 
makeNonLoc(const SymExpr * operand,UnaryOperator::Opcode op,QualType type)105*12c85518Srobert NonLoc SValBuilder::makeNonLoc(const SymExpr *operand, UnaryOperator::Opcode op,
106*12c85518Srobert                                QualType type) {
107*12c85518Srobert   assert(operand);
108*12c85518Srobert   assert(!Loc::isLocType(type));
109*12c85518Srobert   return nonloc::SymbolVal(SymMgr.getUnarySymExpr(operand, op, type));
110*12c85518Srobert }
111*12c85518Srobert 
makeNonLoc(const SymExpr * operand,QualType fromTy,QualType toTy)112*12c85518Srobert nonloc::SymbolVal SValBuilder::makeNonLoc(const SymExpr *operand,
113e5dd7070Spatrick                                           QualType fromTy, QualType toTy) {
114e5dd7070Spatrick   assert(operand);
115e5dd7070Spatrick   assert(!Loc::isLocType(toTy));
116*12c85518Srobert   if (fromTy == toTy)
117*12c85518Srobert     return operand;
118e5dd7070Spatrick   return nonloc::SymbolVal(SymMgr.getCastSymbol(operand, fromTy, toTy));
119e5dd7070Spatrick }
120e5dd7070Spatrick 
convertToArrayIndex(SVal val)121e5dd7070Spatrick SVal SValBuilder::convertToArrayIndex(SVal val) {
122e5dd7070Spatrick   if (val.isUnknownOrUndef())
123e5dd7070Spatrick     return val;
124e5dd7070Spatrick 
125e5dd7070Spatrick   // Common case: we have an appropriately sized integer.
126*12c85518Srobert   if (std::optional<nonloc::ConcreteInt> CI =
127*12c85518Srobert           val.getAs<nonloc::ConcreteInt>()) {
128e5dd7070Spatrick     const llvm::APSInt& I = CI->getValue();
129e5dd7070Spatrick     if (I.getBitWidth() == ArrayIndexWidth && I.isSigned())
130e5dd7070Spatrick       return val;
131e5dd7070Spatrick   }
132e5dd7070Spatrick 
133a9ac8606Spatrick   return evalCast(val, ArrayIndexTy, QualType{});
134e5dd7070Spatrick }
135e5dd7070Spatrick 
makeBoolVal(const CXXBoolLiteralExpr * boolean)136e5dd7070Spatrick nonloc::ConcreteInt SValBuilder::makeBoolVal(const CXXBoolLiteralExpr *boolean){
137e5dd7070Spatrick   return makeTruthVal(boolean->getValue());
138e5dd7070Spatrick }
139e5dd7070Spatrick 
140e5dd7070Spatrick DefinedOrUnknownSVal
getRegionValueSymbolVal(const TypedValueRegion * region)141e5dd7070Spatrick SValBuilder::getRegionValueSymbolVal(const TypedValueRegion *region) {
142e5dd7070Spatrick   QualType T = region->getValueType();
143e5dd7070Spatrick 
144e5dd7070Spatrick   if (T->isNullPtrType())
145e5dd7070Spatrick     return makeZeroVal(T);
146e5dd7070Spatrick 
147e5dd7070Spatrick   if (!SymbolManager::canSymbolicate(T))
148e5dd7070Spatrick     return UnknownVal();
149e5dd7070Spatrick 
150e5dd7070Spatrick   SymbolRef sym = SymMgr.getRegionValueSymbol(region);
151e5dd7070Spatrick 
152e5dd7070Spatrick   if (Loc::isLocType(T))
153e5dd7070Spatrick     return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
154e5dd7070Spatrick 
155e5dd7070Spatrick   return nonloc::SymbolVal(sym);
156e5dd7070Spatrick }
157e5dd7070Spatrick 
conjureSymbolVal(const void * SymbolTag,const Expr * Ex,const LocationContext * LCtx,unsigned Count)158e5dd7070Spatrick DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *SymbolTag,
159e5dd7070Spatrick                                                    const Expr *Ex,
160e5dd7070Spatrick                                                    const LocationContext *LCtx,
161e5dd7070Spatrick                                                    unsigned Count) {
162e5dd7070Spatrick   QualType T = Ex->getType();
163e5dd7070Spatrick 
164e5dd7070Spatrick   if (T->isNullPtrType())
165e5dd7070Spatrick     return makeZeroVal(T);
166e5dd7070Spatrick 
167e5dd7070Spatrick   // Compute the type of the result. If the expression is not an R-value, the
168e5dd7070Spatrick   // result should be a location.
169e5dd7070Spatrick   QualType ExType = Ex->getType();
170e5dd7070Spatrick   if (Ex->isGLValue())
171e5dd7070Spatrick     T = LCtx->getAnalysisDeclContext()->getASTContext().getPointerType(ExType);
172e5dd7070Spatrick 
173e5dd7070Spatrick   return conjureSymbolVal(SymbolTag, Ex, LCtx, T, Count);
174e5dd7070Spatrick }
175e5dd7070Spatrick 
conjureSymbolVal(const void * symbolTag,const Expr * expr,const LocationContext * LCtx,QualType type,unsigned count)176e5dd7070Spatrick DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *symbolTag,
177e5dd7070Spatrick                                                    const Expr *expr,
178e5dd7070Spatrick                                                    const LocationContext *LCtx,
179e5dd7070Spatrick                                                    QualType type,
180e5dd7070Spatrick                                                    unsigned count) {
181e5dd7070Spatrick   if (type->isNullPtrType())
182e5dd7070Spatrick     return makeZeroVal(type);
183e5dd7070Spatrick 
184e5dd7070Spatrick   if (!SymbolManager::canSymbolicate(type))
185e5dd7070Spatrick     return UnknownVal();
186e5dd7070Spatrick 
187e5dd7070Spatrick   SymbolRef sym = SymMgr.conjureSymbol(expr, LCtx, type, count, symbolTag);
188e5dd7070Spatrick 
189e5dd7070Spatrick   if (Loc::isLocType(type))
190e5dd7070Spatrick     return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
191e5dd7070Spatrick 
192e5dd7070Spatrick   return nonloc::SymbolVal(sym);
193e5dd7070Spatrick }
194e5dd7070Spatrick 
conjureSymbolVal(const Stmt * stmt,const LocationContext * LCtx,QualType type,unsigned visitCount)195e5dd7070Spatrick DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const Stmt *stmt,
196e5dd7070Spatrick                                                    const LocationContext *LCtx,
197e5dd7070Spatrick                                                    QualType type,
198e5dd7070Spatrick                                                    unsigned visitCount) {
199e5dd7070Spatrick   if (type->isNullPtrType())
200e5dd7070Spatrick     return makeZeroVal(type);
201e5dd7070Spatrick 
202e5dd7070Spatrick   if (!SymbolManager::canSymbolicate(type))
203e5dd7070Spatrick     return UnknownVal();
204e5dd7070Spatrick 
205e5dd7070Spatrick   SymbolRef sym = SymMgr.conjureSymbol(stmt, LCtx, type, visitCount);
206e5dd7070Spatrick 
207e5dd7070Spatrick   if (Loc::isLocType(type))
208e5dd7070Spatrick     return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
209e5dd7070Spatrick 
210e5dd7070Spatrick   return nonloc::SymbolVal(sym);
211e5dd7070Spatrick }
212e5dd7070Spatrick 
213e5dd7070Spatrick DefinedOrUnknownSVal
getConjuredHeapSymbolVal(const Expr * E,const LocationContext * LCtx,unsigned VisitCount)214e5dd7070Spatrick SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
215e5dd7070Spatrick                                       const LocationContext *LCtx,
216e5dd7070Spatrick                                       unsigned VisitCount) {
217e5dd7070Spatrick   QualType T = E->getType();
218a9ac8606Spatrick   return getConjuredHeapSymbolVal(E, LCtx, T, VisitCount);
219a9ac8606Spatrick }
220e5dd7070Spatrick 
221a9ac8606Spatrick DefinedOrUnknownSVal
getConjuredHeapSymbolVal(const Expr * E,const LocationContext * LCtx,QualType type,unsigned VisitCount)222a9ac8606Spatrick SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
223a9ac8606Spatrick                                       const LocationContext *LCtx,
224a9ac8606Spatrick                                       QualType type, unsigned VisitCount) {
225a9ac8606Spatrick   assert(Loc::isLocType(type));
226a9ac8606Spatrick   assert(SymbolManager::canSymbolicate(type));
227a9ac8606Spatrick   if (type->isNullPtrType())
228a9ac8606Spatrick     return makeZeroVal(type);
229a9ac8606Spatrick 
230a9ac8606Spatrick   SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, type, VisitCount);
231e5dd7070Spatrick   return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym));
232e5dd7070Spatrick }
233e5dd7070Spatrick 
getMetadataSymbolVal(const void * symbolTag,const MemRegion * region,const Expr * expr,QualType type,const LocationContext * LCtx,unsigned count)234e5dd7070Spatrick DefinedSVal SValBuilder::getMetadataSymbolVal(const void *symbolTag,
235e5dd7070Spatrick                                               const MemRegion *region,
236e5dd7070Spatrick                                               const Expr *expr, QualType type,
237e5dd7070Spatrick                                               const LocationContext *LCtx,
238e5dd7070Spatrick                                               unsigned count) {
239e5dd7070Spatrick   assert(SymbolManager::canSymbolicate(type) && "Invalid metadata symbol type");
240e5dd7070Spatrick 
241e5dd7070Spatrick   SymbolRef sym =
242e5dd7070Spatrick       SymMgr.getMetadataSymbol(region, expr, type, LCtx, count, symbolTag);
243e5dd7070Spatrick 
244e5dd7070Spatrick   if (Loc::isLocType(type))
245e5dd7070Spatrick     return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
246e5dd7070Spatrick 
247e5dd7070Spatrick   return nonloc::SymbolVal(sym);
248e5dd7070Spatrick }
249e5dd7070Spatrick 
250e5dd7070Spatrick DefinedOrUnknownSVal
getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,const TypedValueRegion * region)251e5dd7070Spatrick SValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
252e5dd7070Spatrick                                              const TypedValueRegion *region) {
253e5dd7070Spatrick   QualType T = region->getValueType();
254e5dd7070Spatrick 
255e5dd7070Spatrick   if (T->isNullPtrType())
256e5dd7070Spatrick     return makeZeroVal(T);
257e5dd7070Spatrick 
258e5dd7070Spatrick   if (!SymbolManager::canSymbolicate(T))
259e5dd7070Spatrick     return UnknownVal();
260e5dd7070Spatrick 
261e5dd7070Spatrick   SymbolRef sym = SymMgr.getDerivedSymbol(parentSymbol, region);
262e5dd7070Spatrick 
263e5dd7070Spatrick   if (Loc::isLocType(T))
264e5dd7070Spatrick     return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
265e5dd7070Spatrick 
266e5dd7070Spatrick   return nonloc::SymbolVal(sym);
267e5dd7070Spatrick }
268e5dd7070Spatrick 
getMemberPointer(const NamedDecl * ND)269a9ac8606Spatrick DefinedSVal SValBuilder::getMemberPointer(const NamedDecl *ND) {
270*12c85518Srobert   assert(!ND || (isa<CXXMethodDecl, FieldDecl, IndirectFieldDecl>(ND)));
271e5dd7070Spatrick 
272a9ac8606Spatrick   if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
273e5dd7070Spatrick     // Sema treats pointers to static member functions as have function pointer
274e5dd7070Spatrick     // type, so return a function pointer for the method.
275e5dd7070Spatrick     // We don't need to play a similar trick for static member fields
276e5dd7070Spatrick     // because these are represented as plain VarDecls and not FieldDecls
277e5dd7070Spatrick     // in the AST.
278e5dd7070Spatrick     if (MD->isStatic())
279e5dd7070Spatrick       return getFunctionPointer(MD);
280e5dd7070Spatrick   }
281e5dd7070Spatrick 
282a9ac8606Spatrick   return nonloc::PointerToMember(ND);
283e5dd7070Spatrick }
284e5dd7070Spatrick 
getFunctionPointer(const FunctionDecl * func)285e5dd7070Spatrick DefinedSVal SValBuilder::getFunctionPointer(const FunctionDecl *func) {
286e5dd7070Spatrick   return loc::MemRegionVal(MemMgr.getFunctionCodeRegion(func));
287e5dd7070Spatrick }
288e5dd7070Spatrick 
getBlockPointer(const BlockDecl * block,CanQualType locTy,const LocationContext * locContext,unsigned blockCount)289e5dd7070Spatrick DefinedSVal SValBuilder::getBlockPointer(const BlockDecl *block,
290e5dd7070Spatrick                                          CanQualType locTy,
291e5dd7070Spatrick                                          const LocationContext *locContext,
292e5dd7070Spatrick                                          unsigned blockCount) {
293e5dd7070Spatrick   const BlockCodeRegion *BC =
294e5dd7070Spatrick     MemMgr.getBlockCodeRegion(block, locTy, locContext->getAnalysisDeclContext());
295e5dd7070Spatrick   const BlockDataRegion *BD = MemMgr.getBlockDataRegion(BC, locContext,
296e5dd7070Spatrick                                                         blockCount);
297e5dd7070Spatrick   return loc::MemRegionVal(BD);
298e5dd7070Spatrick }
299e5dd7070Spatrick 
300*12c85518Srobert std::optional<loc::MemRegionVal>
getCastedMemRegionVal(const MemRegion * R,QualType Ty)301a9ac8606Spatrick SValBuilder::getCastedMemRegionVal(const MemRegion *R, QualType Ty) {
302a9ac8606Spatrick   if (auto OptR = StateMgr.getStoreManager().castRegion(R, Ty))
303a9ac8606Spatrick     return loc::MemRegionVal(*OptR);
304*12c85518Srobert   return std::nullopt;
305a9ac8606Spatrick }
306a9ac8606Spatrick 
307e5dd7070Spatrick /// Return a memory region for the 'this' object reference.
getCXXThis(const CXXMethodDecl * D,const StackFrameContext * SFC)308e5dd7070Spatrick loc::MemRegionVal SValBuilder::getCXXThis(const CXXMethodDecl *D,
309e5dd7070Spatrick                                           const StackFrameContext *SFC) {
310e5dd7070Spatrick   return loc::MemRegionVal(
311e5dd7070Spatrick       getRegionManager().getCXXThisRegion(D->getThisType(), SFC));
312e5dd7070Spatrick }
313e5dd7070Spatrick 
314e5dd7070Spatrick /// Return a memory region for the 'this' object reference.
getCXXThis(const CXXRecordDecl * D,const StackFrameContext * SFC)315e5dd7070Spatrick loc::MemRegionVal SValBuilder::getCXXThis(const CXXRecordDecl *D,
316e5dd7070Spatrick                                           const StackFrameContext *SFC) {
317e5dd7070Spatrick   const Type *T = D->getTypeForDecl();
318e5dd7070Spatrick   QualType PT = getContext().getPointerType(QualType(T, 0));
319e5dd7070Spatrick   return loc::MemRegionVal(getRegionManager().getCXXThisRegion(PT, SFC));
320e5dd7070Spatrick }
321e5dd7070Spatrick 
getConstantVal(const Expr * E)322*12c85518Srobert std::optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
323e5dd7070Spatrick   E = E->IgnoreParens();
324e5dd7070Spatrick 
325e5dd7070Spatrick   switch (E->getStmtClass()) {
326e5dd7070Spatrick   // Handle expressions that we treat differently from the AST's constant
327e5dd7070Spatrick   // evaluator.
328e5dd7070Spatrick   case Stmt::AddrLabelExprClass:
329e5dd7070Spatrick     return makeLoc(cast<AddrLabelExpr>(E));
330e5dd7070Spatrick 
331e5dd7070Spatrick   case Stmt::CXXScalarValueInitExprClass:
332e5dd7070Spatrick   case Stmt::ImplicitValueInitExprClass:
333e5dd7070Spatrick     return makeZeroVal(E->getType());
334e5dd7070Spatrick 
335e5dd7070Spatrick   case Stmt::ObjCStringLiteralClass: {
336e5dd7070Spatrick     const auto *SL = cast<ObjCStringLiteral>(E);
337e5dd7070Spatrick     return makeLoc(getRegionManager().getObjCStringRegion(SL));
338e5dd7070Spatrick   }
339e5dd7070Spatrick 
340e5dd7070Spatrick   case Stmt::StringLiteralClass: {
341e5dd7070Spatrick     const auto *SL = cast<StringLiteral>(E);
342e5dd7070Spatrick     return makeLoc(getRegionManager().getStringRegion(SL));
343e5dd7070Spatrick   }
344e5dd7070Spatrick 
345a9ac8606Spatrick   case Stmt::PredefinedExprClass: {
346a9ac8606Spatrick     const auto *PE = cast<PredefinedExpr>(E);
347a9ac8606Spatrick     assert(PE->getFunctionName() &&
348a9ac8606Spatrick            "Since we analyze only instantiated functions, PredefinedExpr "
349a9ac8606Spatrick            "should have a function name.");
350a9ac8606Spatrick     return makeLoc(getRegionManager().getStringRegion(PE->getFunctionName()));
351a9ac8606Spatrick   }
352a9ac8606Spatrick 
353e5dd7070Spatrick   // Fast-path some expressions to avoid the overhead of going through the AST's
354e5dd7070Spatrick   // constant evaluator
355e5dd7070Spatrick   case Stmt::CharacterLiteralClass: {
356e5dd7070Spatrick     const auto *C = cast<CharacterLiteral>(E);
357e5dd7070Spatrick     return makeIntVal(C->getValue(), C->getType());
358e5dd7070Spatrick   }
359e5dd7070Spatrick 
360e5dd7070Spatrick   case Stmt::CXXBoolLiteralExprClass:
361e5dd7070Spatrick     return makeBoolVal(cast<CXXBoolLiteralExpr>(E));
362e5dd7070Spatrick 
363e5dd7070Spatrick   case Stmt::TypeTraitExprClass: {
364e5dd7070Spatrick     const auto *TE = cast<TypeTraitExpr>(E);
365e5dd7070Spatrick     return makeTruthVal(TE->getValue(), TE->getType());
366e5dd7070Spatrick   }
367e5dd7070Spatrick 
368e5dd7070Spatrick   case Stmt::IntegerLiteralClass:
369e5dd7070Spatrick     return makeIntVal(cast<IntegerLiteral>(E));
370e5dd7070Spatrick 
371e5dd7070Spatrick   case Stmt::ObjCBoolLiteralExprClass:
372e5dd7070Spatrick     return makeBoolVal(cast<ObjCBoolLiteralExpr>(E));
373e5dd7070Spatrick 
374e5dd7070Spatrick   case Stmt::CXXNullPtrLiteralExprClass:
375*12c85518Srobert     return makeNullWithType(E->getType());
376e5dd7070Spatrick 
377e5dd7070Spatrick   case Stmt::CStyleCastExprClass:
378e5dd7070Spatrick   case Stmt::CXXFunctionalCastExprClass:
379e5dd7070Spatrick   case Stmt::CXXConstCastExprClass:
380e5dd7070Spatrick   case Stmt::CXXReinterpretCastExprClass:
381e5dd7070Spatrick   case Stmt::CXXStaticCastExprClass:
382e5dd7070Spatrick   case Stmt::ImplicitCastExprClass: {
383e5dd7070Spatrick     const auto *CE = cast<CastExpr>(E);
384e5dd7070Spatrick     switch (CE->getCastKind()) {
385e5dd7070Spatrick     default:
386e5dd7070Spatrick       break;
387e5dd7070Spatrick     case CK_ArrayToPointerDecay:
388e5dd7070Spatrick     case CK_IntegralToPointer:
389e5dd7070Spatrick     case CK_NoOp:
390e5dd7070Spatrick     case CK_BitCast: {
391e5dd7070Spatrick       const Expr *SE = CE->getSubExpr();
392*12c85518Srobert       std::optional<SVal> Val = getConstantVal(SE);
393e5dd7070Spatrick       if (!Val)
394*12c85518Srobert         return std::nullopt;
395e5dd7070Spatrick       return evalCast(*Val, CE->getType(), SE->getType());
396e5dd7070Spatrick     }
397e5dd7070Spatrick     }
398e5dd7070Spatrick     // FALLTHROUGH
399*12c85518Srobert     [[fallthrough]];
400e5dd7070Spatrick   }
401e5dd7070Spatrick 
402e5dd7070Spatrick   // If we don't have a special case, fall back to the AST's constant evaluator.
403e5dd7070Spatrick   default: {
404e5dd7070Spatrick     // Don't try to come up with a value for materialized temporaries.
405e5dd7070Spatrick     if (E->isGLValue())
406*12c85518Srobert       return std::nullopt;
407e5dd7070Spatrick 
408e5dd7070Spatrick     ASTContext &Ctx = getContext();
409e5dd7070Spatrick     Expr::EvalResult Result;
410e5dd7070Spatrick     if (E->EvaluateAsInt(Result, Ctx))
411e5dd7070Spatrick       return makeIntVal(Result.Val.getInt());
412e5dd7070Spatrick 
413e5dd7070Spatrick     if (Loc::isLocType(E->getType()))
414e5dd7070Spatrick       if (E->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))
415*12c85518Srobert         return makeNullWithType(E->getType());
416e5dd7070Spatrick 
417*12c85518Srobert     return std::nullopt;
418e5dd7070Spatrick   }
419e5dd7070Spatrick   }
420e5dd7070Spatrick }
421e5dd7070Spatrick 
makeSymExprValNN(BinaryOperator::Opcode Op,NonLoc LHS,NonLoc RHS,QualType ResultTy)422e5dd7070Spatrick SVal SValBuilder::makeSymExprValNN(BinaryOperator::Opcode Op,
423e5dd7070Spatrick                                    NonLoc LHS, NonLoc RHS,
424e5dd7070Spatrick                                    QualType ResultTy) {
425a9ac8606Spatrick   SymbolRef symLHS = LHS.getAsSymbol();
426a9ac8606Spatrick   SymbolRef symRHS = RHS.getAsSymbol();
427e5dd7070Spatrick 
428e5dd7070Spatrick   // TODO: When the Max Complexity is reached, we should conjure a symbol
429e5dd7070Spatrick   // instead of generating an Unknown value and propagate the taint info to it.
430*12c85518Srobert   const unsigned MaxComp = AnOpts.MaxSymbolComplexity;
431e5dd7070Spatrick 
432e5dd7070Spatrick   if (symLHS && symRHS &&
433e5dd7070Spatrick       (symLHS->computeComplexity() + symRHS->computeComplexity()) <  MaxComp)
434e5dd7070Spatrick     return makeNonLoc(symLHS, Op, symRHS, ResultTy);
435e5dd7070Spatrick 
436e5dd7070Spatrick   if (symLHS && symLHS->computeComplexity() < MaxComp)
437*12c85518Srobert     if (std::optional<nonloc::ConcreteInt> rInt =
438*12c85518Srobert             RHS.getAs<nonloc::ConcreteInt>())
439e5dd7070Spatrick       return makeNonLoc(symLHS, Op, rInt->getValue(), ResultTy);
440e5dd7070Spatrick 
441e5dd7070Spatrick   if (symRHS && symRHS->computeComplexity() < MaxComp)
442*12c85518Srobert     if (std::optional<nonloc::ConcreteInt> lInt =
443*12c85518Srobert             LHS.getAs<nonloc::ConcreteInt>())
444e5dd7070Spatrick       return makeNonLoc(lInt->getValue(), Op, symRHS, ResultTy);
445e5dd7070Spatrick 
446e5dd7070Spatrick   return UnknownVal();
447e5dd7070Spatrick }
448e5dd7070Spatrick 
evalMinus(NonLoc X)449*12c85518Srobert SVal SValBuilder::evalMinus(NonLoc X) {
450*12c85518Srobert   switch (X.getSubKind()) {
451*12c85518Srobert   case nonloc::ConcreteIntKind:
452*12c85518Srobert     return makeIntVal(-X.castAs<nonloc::ConcreteInt>().getValue());
453*12c85518Srobert   case nonloc::SymbolValKind:
454*12c85518Srobert     return makeNonLoc(X.castAs<nonloc::SymbolVal>().getSymbol(), UO_Minus,
455*12c85518Srobert                       X.getType(Context));
456*12c85518Srobert   default:
457*12c85518Srobert     return UnknownVal();
458*12c85518Srobert   }
459*12c85518Srobert }
460*12c85518Srobert 
evalComplement(NonLoc X)461*12c85518Srobert SVal SValBuilder::evalComplement(NonLoc X) {
462*12c85518Srobert   switch (X.getSubKind()) {
463*12c85518Srobert   case nonloc::ConcreteIntKind:
464*12c85518Srobert     return makeIntVal(~X.castAs<nonloc::ConcreteInt>().getValue());
465*12c85518Srobert   case nonloc::SymbolValKind:
466*12c85518Srobert     return makeNonLoc(X.castAs<nonloc::SymbolVal>().getSymbol(), UO_Not,
467*12c85518Srobert                       X.getType(Context));
468*12c85518Srobert   default:
469*12c85518Srobert     return UnknownVal();
470*12c85518Srobert   }
471*12c85518Srobert }
472*12c85518Srobert 
evalUnaryOp(ProgramStateRef state,UnaryOperator::Opcode opc,SVal operand,QualType type)473*12c85518Srobert SVal SValBuilder::evalUnaryOp(ProgramStateRef state, UnaryOperator::Opcode opc,
474*12c85518Srobert                  SVal operand, QualType type) {
475*12c85518Srobert   auto OpN = operand.getAs<NonLoc>();
476*12c85518Srobert   if (!OpN)
477*12c85518Srobert     return UnknownVal();
478*12c85518Srobert 
479*12c85518Srobert   if (opc == UO_Minus)
480*12c85518Srobert     return evalMinus(*OpN);
481*12c85518Srobert   if (opc == UO_Not)
482*12c85518Srobert     return evalComplement(*OpN);
483*12c85518Srobert   llvm_unreachable("Unexpected unary operator");
484*12c85518Srobert }
485*12c85518Srobert 
evalBinOp(ProgramStateRef state,BinaryOperator::Opcode op,SVal lhs,SVal rhs,QualType type)486e5dd7070Spatrick SVal SValBuilder::evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
487e5dd7070Spatrick                             SVal lhs, SVal rhs, QualType type) {
488e5dd7070Spatrick   if (lhs.isUndef() || rhs.isUndef())
489e5dd7070Spatrick     return UndefinedVal();
490e5dd7070Spatrick 
491e5dd7070Spatrick   if (lhs.isUnknown() || rhs.isUnknown())
492e5dd7070Spatrick     return UnknownVal();
493e5dd7070Spatrick 
494*12c85518Srobert   if (isa<nonloc::LazyCompoundVal>(lhs) || isa<nonloc::LazyCompoundVal>(rhs)) {
495e5dd7070Spatrick     return UnknownVal();
496e5dd7070Spatrick   }
497e5dd7070Spatrick 
498a9ac8606Spatrick   if (op == BinaryOperatorKind::BO_Cmp) {
499a9ac8606Spatrick     // We can't reason about C++20 spaceship operator yet.
500a9ac8606Spatrick     //
501a9ac8606Spatrick     // FIXME: Support C++20 spaceship operator.
502a9ac8606Spatrick     //        The main problem here is that the result is not integer.
503a9ac8606Spatrick     return UnknownVal();
504a9ac8606Spatrick   }
505a9ac8606Spatrick 
506*12c85518Srobert   if (std::optional<Loc> LV = lhs.getAs<Loc>()) {
507*12c85518Srobert     if (std::optional<Loc> RV = rhs.getAs<Loc>())
508e5dd7070Spatrick       return evalBinOpLL(state, op, *LV, *RV, type);
509e5dd7070Spatrick 
510e5dd7070Spatrick     return evalBinOpLN(state, op, *LV, rhs.castAs<NonLoc>(), type);
511e5dd7070Spatrick   }
512e5dd7070Spatrick 
513*12c85518Srobert   if (const std::optional<Loc> RV = rhs.getAs<Loc>()) {
514*12c85518Srobert     const auto IsCommutative = [](BinaryOperatorKind Op) {
515*12c85518Srobert       return Op == BO_Mul || Op == BO_Add || Op == BO_And || Op == BO_Xor ||
516*12c85518Srobert              Op == BO_Or;
517*12c85518Srobert     };
518e5dd7070Spatrick 
519*12c85518Srobert     if (IsCommutative(op)) {
520*12c85518Srobert       // Swap operands.
521e5dd7070Spatrick       return evalBinOpLN(state, op, *RV, lhs.castAs<NonLoc>(), type);
522e5dd7070Spatrick     }
523e5dd7070Spatrick 
524*12c85518Srobert     // If the right operand is a concrete int location then we have nothing
525*12c85518Srobert     // better but to treat it as a simple nonloc.
526*12c85518Srobert     if (auto RV = rhs.getAs<loc::ConcreteInt>()) {
527*12c85518Srobert       const nonloc::ConcreteInt RhsAsLoc = makeIntVal(RV->getValue());
528*12c85518Srobert       return evalBinOpNN(state, op, lhs.castAs<NonLoc>(), RhsAsLoc, type);
529*12c85518Srobert     }
530*12c85518Srobert   }
531*12c85518Srobert 
532e5dd7070Spatrick   return evalBinOpNN(state, op, lhs.castAs<NonLoc>(), rhs.castAs<NonLoc>(),
533e5dd7070Spatrick                      type);
534e5dd7070Spatrick }
535e5dd7070Spatrick 
areEqual(ProgramStateRef state,SVal lhs,SVal rhs)536e5dd7070Spatrick ConditionTruthVal SValBuilder::areEqual(ProgramStateRef state, SVal lhs,
537e5dd7070Spatrick                                         SVal rhs) {
538e5dd7070Spatrick   return state->isNonNull(evalEQ(state, lhs, rhs));
539e5dd7070Spatrick }
540e5dd7070Spatrick 
evalEQ(ProgramStateRef state,SVal lhs,SVal rhs)541e5dd7070Spatrick SVal SValBuilder::evalEQ(ProgramStateRef state, SVal lhs, SVal rhs) {
542e5dd7070Spatrick   return evalBinOp(state, BO_EQ, lhs, rhs, getConditionType());
543e5dd7070Spatrick }
544e5dd7070Spatrick 
evalEQ(ProgramStateRef state,DefinedOrUnknownSVal lhs,DefinedOrUnknownSVal rhs)545e5dd7070Spatrick DefinedOrUnknownSVal SValBuilder::evalEQ(ProgramStateRef state,
546e5dd7070Spatrick                                          DefinedOrUnknownSVal lhs,
547e5dd7070Spatrick                                          DefinedOrUnknownSVal rhs) {
548e5dd7070Spatrick   return evalEQ(state, static_cast<SVal>(lhs), static_cast<SVal>(rhs))
549e5dd7070Spatrick       .castAs<DefinedOrUnknownSVal>();
550e5dd7070Spatrick }
551e5dd7070Spatrick 
552e5dd7070Spatrick /// Recursively check if the pointer types are equal modulo const, volatile,
553e5dd7070Spatrick /// and restrict qualifiers. Also, assume that all types are similar to 'void'.
554e5dd7070Spatrick /// Assumes the input types are canonical.
shouldBeModeledWithNoOp(ASTContext & Context,QualType ToTy,QualType FromTy)555e5dd7070Spatrick static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy,
556e5dd7070Spatrick                                                          QualType FromTy) {
557e5dd7070Spatrick   while (Context.UnwrapSimilarTypes(ToTy, FromTy)) {
558e5dd7070Spatrick     Qualifiers Quals1, Quals2;
559e5dd7070Spatrick     ToTy = Context.getUnqualifiedArrayType(ToTy, Quals1);
560e5dd7070Spatrick     FromTy = Context.getUnqualifiedArrayType(FromTy, Quals2);
561e5dd7070Spatrick 
562e5dd7070Spatrick     // Make sure that non-cvr-qualifiers the other qualifiers (e.g., address
563e5dd7070Spatrick     // spaces) are identical.
564e5dd7070Spatrick     Quals1.removeCVRQualifiers();
565e5dd7070Spatrick     Quals2.removeCVRQualifiers();
566e5dd7070Spatrick     if (Quals1 != Quals2)
567e5dd7070Spatrick       return false;
568e5dd7070Spatrick   }
569e5dd7070Spatrick 
570e5dd7070Spatrick   // If we are casting to void, the 'From' value can be used to represent the
571e5dd7070Spatrick   // 'To' value.
572e5dd7070Spatrick   //
573e5dd7070Spatrick   // FIXME: Doing this after unwrapping the types doesn't make any sense. A
574e5dd7070Spatrick   // cast from 'int**' to 'void**' is not special in the way that a cast from
575e5dd7070Spatrick   // 'int*' to 'void*' is.
576e5dd7070Spatrick   if (ToTy->isVoidType())
577e5dd7070Spatrick     return true;
578e5dd7070Spatrick 
579e5dd7070Spatrick   if (ToTy != FromTy)
580e5dd7070Spatrick     return false;
581e5dd7070Spatrick 
582e5dd7070Spatrick   return true;
583e5dd7070Spatrick }
584e5dd7070Spatrick 
585e5dd7070Spatrick // Handles casts of type CK_IntegralCast.
586e5dd7070Spatrick // At the moment, this function will redirect to evalCast, except when the range
587e5dd7070Spatrick // of the original value is known to be greater than the max of the target type.
evalIntegralCast(ProgramStateRef state,SVal val,QualType castTy,QualType originalTy)588e5dd7070Spatrick SVal SValBuilder::evalIntegralCast(ProgramStateRef state, SVal val,
589e5dd7070Spatrick                                    QualType castTy, QualType originalTy) {
590e5dd7070Spatrick   // No truncations if target type is big enough.
591e5dd7070Spatrick   if (getContext().getTypeSize(castTy) >= getContext().getTypeSize(originalTy))
592e5dd7070Spatrick     return evalCast(val, castTy, originalTy);
593e5dd7070Spatrick 
594a9ac8606Spatrick   SymbolRef se = val.getAsSymbol();
595e5dd7070Spatrick   if (!se) // Let evalCast handle non symbolic expressions.
596e5dd7070Spatrick     return evalCast(val, castTy, originalTy);
597e5dd7070Spatrick 
598e5dd7070Spatrick   // Find the maximum value of the target type.
599e5dd7070Spatrick   APSIntType ToType(getContext().getTypeSize(castTy),
600e5dd7070Spatrick                     castTy->isUnsignedIntegerType());
601e5dd7070Spatrick   llvm::APSInt ToTypeMax = ToType.getMaxValue();
602e5dd7070Spatrick   NonLoc ToTypeMaxVal =
603e5dd7070Spatrick       makeIntVal(ToTypeMax.isUnsigned() ? ToTypeMax.getZExtValue()
604e5dd7070Spatrick                                         : ToTypeMax.getSExtValue(),
605e5dd7070Spatrick                  castTy)
606e5dd7070Spatrick           .castAs<NonLoc>();
607e5dd7070Spatrick   // Check the range of the symbol being casted against the maximum value of the
608e5dd7070Spatrick   // target type.
609e5dd7070Spatrick   NonLoc FromVal = val.castAs<NonLoc>();
610e5dd7070Spatrick   QualType CmpTy = getConditionType();
611e5dd7070Spatrick   NonLoc CompVal =
612e5dd7070Spatrick       evalBinOpNN(state, BO_LE, FromVal, ToTypeMaxVal, CmpTy).castAs<NonLoc>();
613e5dd7070Spatrick   ProgramStateRef IsNotTruncated, IsTruncated;
614e5dd7070Spatrick   std::tie(IsNotTruncated, IsTruncated) = state->assume(CompVal);
615e5dd7070Spatrick   if (!IsNotTruncated && IsTruncated) {
616e5dd7070Spatrick     // Symbol is truncated so we evaluate it as a cast.
617*12c85518Srobert     return makeNonLoc(se, originalTy, castTy);
618e5dd7070Spatrick   }
619e5dd7070Spatrick   return evalCast(val, castTy, originalTy);
620e5dd7070Spatrick }
621e5dd7070Spatrick 
622a9ac8606Spatrick //===----------------------------------------------------------------------===//
623*12c85518Srobert // Cast method.
624*12c85518Srobert // `evalCast` and its helper `EvalCastVisitor`
625a9ac8606Spatrick //===----------------------------------------------------------------------===//
626e5dd7070Spatrick 
627*12c85518Srobert namespace {
628*12c85518Srobert class EvalCastVisitor : public SValVisitor<EvalCastVisitor, SVal> {
629*12c85518Srobert private:
630*12c85518Srobert   SValBuilder &VB;
631*12c85518Srobert   ASTContext &Context;
632*12c85518Srobert   QualType CastTy, OriginalTy;
633*12c85518Srobert 
634*12c85518Srobert public:
EvalCastVisitor(SValBuilder & VB,QualType CastTy,QualType OriginalTy)635*12c85518Srobert   EvalCastVisitor(SValBuilder &VB, QualType CastTy, QualType OriginalTy)
636*12c85518Srobert       : VB(VB), Context(VB.getContext()), CastTy(CastTy),
637*12c85518Srobert         OriginalTy(OriginalTy) {}
638*12c85518Srobert 
Visit(SVal V)639*12c85518Srobert   SVal Visit(SVal V) {
640a9ac8606Spatrick     if (CastTy.isNull())
641a9ac8606Spatrick       return V;
642a9ac8606Spatrick 
643a9ac8606Spatrick     CastTy = Context.getCanonicalType(CastTy);
644a9ac8606Spatrick 
645a9ac8606Spatrick     const bool IsUnknownOriginalType = OriginalTy.isNull();
646a9ac8606Spatrick     if (!IsUnknownOriginalType) {
647a9ac8606Spatrick       OriginalTy = Context.getCanonicalType(OriginalTy);
648a9ac8606Spatrick 
649a9ac8606Spatrick       if (CastTy == OriginalTy)
650a9ac8606Spatrick         return V;
651a9ac8606Spatrick 
652a9ac8606Spatrick       // FIXME: Move this check to the most appropriate
653a9ac8606Spatrick       // evalCastKind/evalCastSubKind function. For const casts, casts to void,
654a9ac8606Spatrick       // just propagate the value.
655a9ac8606Spatrick       if (!CastTy->isVariableArrayType() && !OriginalTy->isVariableArrayType())
656a9ac8606Spatrick         if (shouldBeModeledWithNoOp(Context, Context.getPointerType(CastTy),
657a9ac8606Spatrick                                     Context.getPointerType(OriginalTy)))
658a9ac8606Spatrick           return V;
659a9ac8606Spatrick     }
660*12c85518Srobert     return SValVisitor::Visit(V);
661a9ac8606Spatrick   }
VisitUndefinedVal(UndefinedVal V)662*12c85518Srobert   SVal VisitUndefinedVal(UndefinedVal V) { return V; }
VisitUnknownVal(UnknownVal V)663*12c85518Srobert   SVal VisitUnknownVal(UnknownVal V) { return V; }
VisitLocConcreteInt(loc::ConcreteInt V)664*12c85518Srobert   SVal VisitLocConcreteInt(loc::ConcreteInt V) {
665a9ac8606Spatrick     // Pointer to bool.
666a9ac8606Spatrick     if (CastTy->isBooleanType())
667*12c85518Srobert       return VB.makeTruthVal(V.getValue().getBoolValue(), CastTy);
668a9ac8606Spatrick 
669a9ac8606Spatrick     // Pointer to integer.
670a9ac8606Spatrick     if (CastTy->isIntegralOrEnumerationType()) {
671a9ac8606Spatrick       llvm::APSInt Value = V.getValue();
672*12c85518Srobert       VB.getBasicValueFactory().getAPSIntType(CastTy).apply(Value);
673*12c85518Srobert       return VB.makeIntVal(Value);
674a9ac8606Spatrick     }
675a9ac8606Spatrick 
676a9ac8606Spatrick     // Pointer to any pointer.
677*12c85518Srobert     if (Loc::isLocType(CastTy)) {
678*12c85518Srobert       llvm::APSInt Value = V.getValue();
679*12c85518Srobert       VB.getBasicValueFactory().getAPSIntType(CastTy).apply(Value);
680*12c85518Srobert       return loc::ConcreteInt(VB.getBasicValueFactory().getValue(Value));
681*12c85518Srobert     }
682a9ac8606Spatrick 
683a9ac8606Spatrick     // Pointer to whatever else.
684e5dd7070Spatrick     return UnknownVal();
685e5dd7070Spatrick   }
VisitLocGotoLabel(loc::GotoLabel V)686*12c85518Srobert   SVal VisitLocGotoLabel(loc::GotoLabel V) {
687a9ac8606Spatrick     // Pointer to bool.
688a9ac8606Spatrick     if (CastTy->isBooleanType())
689a9ac8606Spatrick       // Labels are always true.
690*12c85518Srobert       return VB.makeTruthVal(true, CastTy);
691e5dd7070Spatrick 
692a9ac8606Spatrick     // Pointer to integer.
693a9ac8606Spatrick     if (CastTy->isIntegralOrEnumerationType()) {
694a9ac8606Spatrick       const unsigned BitWidth = Context.getIntWidth(CastTy);
695*12c85518Srobert       return VB.makeLocAsInteger(V, BitWidth);
696e5dd7070Spatrick     }
697e5dd7070Spatrick 
698a9ac8606Spatrick     const bool IsUnknownOriginalType = OriginalTy.isNull();
699a9ac8606Spatrick     if (!IsUnknownOriginalType) {
700a9ac8606Spatrick       // Array to pointer.
701a9ac8606Spatrick       if (isa<ArrayType>(OriginalTy))
702a9ac8606Spatrick         if (CastTy->isPointerType() || CastTy->isReferenceType())
703a9ac8606Spatrick           return UnknownVal();
704e5dd7070Spatrick     }
705e5dd7070Spatrick 
706a9ac8606Spatrick     // Pointer to any pointer.
707a9ac8606Spatrick     if (Loc::isLocType(CastTy))
708a9ac8606Spatrick       return V;
709a9ac8606Spatrick 
710a9ac8606Spatrick     // Pointer to whatever else.
711a9ac8606Spatrick     return UnknownVal();
712a9ac8606Spatrick   }
VisitLocMemRegionVal(loc::MemRegionVal V)713*12c85518Srobert   SVal VisitLocMemRegionVal(loc::MemRegionVal V) {
714a9ac8606Spatrick     // Pointer to bool.
715a9ac8606Spatrick     if (CastTy->isBooleanType()) {
716a9ac8606Spatrick       const MemRegion *R = V.getRegion();
717a9ac8606Spatrick       if (const FunctionCodeRegion *FTR = dyn_cast<FunctionCodeRegion>(R))
718a9ac8606Spatrick         if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FTR->getDecl()))
719a9ac8606Spatrick           if (FD->isWeak())
720a9ac8606Spatrick             // FIXME: Currently we are using an extent symbol here,
721a9ac8606Spatrick             // because there are no generic region address metadata
722a9ac8606Spatrick             // symbols to use, only content metadata.
723*12c85518Srobert             return nonloc::SymbolVal(
724*12c85518Srobert                 VB.getSymbolManager().getExtentSymbol(FTR));
725a9ac8606Spatrick 
726a9ac8606Spatrick       if (const SymbolicRegion *SymR = R->getSymbolicBase()) {
727a9ac8606Spatrick         SymbolRef Sym = SymR->getSymbol();
728a9ac8606Spatrick         QualType Ty = Sym->getType();
729a9ac8606Spatrick         // This change is needed for architectures with varying
730a9ac8606Spatrick         // pointer widths. See the amdgcn opencl reproducer with
731a9ac8606Spatrick         // this change as an example: solver-sym-simplification-ptr-bool.cl
732*12c85518Srobert         if (!Ty->isReferenceType())
733*12c85518Srobert           return VB.makeNonLoc(
734*12c85518Srobert               Sym, BO_NE, VB.getBasicValueFactory().getZeroWithTypeSize(Ty),
735*12c85518Srobert               CastTy);
736a9ac8606Spatrick       }
737a9ac8606Spatrick       // Non-symbolic memory regions are always true.
738*12c85518Srobert       return VB.makeTruthVal(true, CastTy);
739a9ac8606Spatrick     }
740a9ac8606Spatrick 
741a9ac8606Spatrick     const bool IsUnknownOriginalType = OriginalTy.isNull();
742a9ac8606Spatrick     // Try to cast to array
743a9ac8606Spatrick     const auto *ArrayTy =
744a9ac8606Spatrick         IsUnknownOriginalType
745a9ac8606Spatrick             ? nullptr
746a9ac8606Spatrick             : dyn_cast<ArrayType>(OriginalTy.getCanonicalType());
747a9ac8606Spatrick 
748a9ac8606Spatrick     // Pointer to integer.
749a9ac8606Spatrick     if (CastTy->isIntegralOrEnumerationType()) {
750a9ac8606Spatrick       SVal Val = V;
751a9ac8606Spatrick       // Array to integer.
752a9ac8606Spatrick       if (ArrayTy) {
753e5dd7070Spatrick         // We will always decay to a pointer.
754a9ac8606Spatrick         QualType ElemTy = ArrayTy->getElementType();
755*12c85518Srobert         Val = VB.getStateManager().ArrayToPointer(V, ElemTy);
756e5dd7070Spatrick         // FIXME: Keep these here for now in case we decide soon that we
757e5dd7070Spatrick         // need the original decayed type.
758e5dd7070Spatrick         //    QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
759e5dd7070Spatrick         //    QualType pointerTy = C.getPointerType(elemTy);
760a9ac8606Spatrick       }
761a9ac8606Spatrick       const unsigned BitWidth = Context.getIntWidth(CastTy);
762*12c85518Srobert       return VB.makeLocAsInteger(Val.castAs<Loc>(), BitWidth);
763e5dd7070Spatrick     }
764e5dd7070Spatrick 
765a9ac8606Spatrick     // Pointer to pointer.
766a9ac8606Spatrick     if (Loc::isLocType(CastTy)) {
767e5dd7070Spatrick 
768a9ac8606Spatrick       if (IsUnknownOriginalType) {
769a9ac8606Spatrick         // When retrieving symbolic pointer and expecting a non-void pointer,
770a9ac8606Spatrick         // wrap them into element regions of the expected type if necessary.
771a9ac8606Spatrick         // It is necessary to make sure that the retrieved value makes sense,
772a9ac8606Spatrick         // because there's no other cast in the AST that would tell us to cast
773a9ac8606Spatrick         // it to the correct pointer type. We might need to do that for non-void
774a9ac8606Spatrick         // pointers as well.
775a9ac8606Spatrick         // FIXME: We really need a single good function to perform casts for us
776a9ac8606Spatrick         // correctly every time we need it.
777a9ac8606Spatrick         const MemRegion *R = V.getRegion();
778a9ac8606Spatrick         if (CastTy->isPointerType() && !CastTy->isVoidPointerType()) {
779a9ac8606Spatrick           if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
780a9ac8606Spatrick             QualType SRTy = SR->getSymbol()->getType();
781*12c85518Srobert 
782*12c85518Srobert             auto HasSameUnqualifiedPointeeType = [](QualType ty1,
783*12c85518Srobert                                                     QualType ty2) {
784*12c85518Srobert               return ty1->getPointeeType().getCanonicalType().getTypePtr() ==
785*12c85518Srobert                      ty2->getPointeeType().getCanonicalType().getTypePtr();
786*12c85518Srobert             };
787*12c85518Srobert             if (!HasSameUnqualifiedPointeeType(SRTy, CastTy)) {
788*12c85518Srobert               if (auto OptMemRegV = VB.getCastedMemRegionVal(SR, CastTy))
789a9ac8606Spatrick                 return *OptMemRegV;
790e5dd7070Spatrick             }
791a9ac8606Spatrick           }
792a9ac8606Spatrick         }
793a9ac8606Spatrick         // Next fixes pointer dereference using type different from its initial
794a9ac8606Spatrick         // one. See PR37503 and PR49007 for details.
795a9ac8606Spatrick         if (const auto *ER = dyn_cast<ElementRegion>(R)) {
796*12c85518Srobert           if (auto OptMemRegV = VB.getCastedMemRegionVal(ER, CastTy))
797a9ac8606Spatrick             return *OptMemRegV;
798a9ac8606Spatrick         }
799a9ac8606Spatrick 
800a9ac8606Spatrick         return V;
801a9ac8606Spatrick       }
802a9ac8606Spatrick 
803a9ac8606Spatrick       if (OriginalTy->isIntegralOrEnumerationType() ||
804*12c85518Srobert           OriginalTy->isBlockPointerType() ||
805*12c85518Srobert           OriginalTy->isFunctionPointerType())
806a9ac8606Spatrick         return V;
807a9ac8606Spatrick 
808a9ac8606Spatrick       // Array to pointer.
809a9ac8606Spatrick       if (ArrayTy) {
810a9ac8606Spatrick         // Are we casting from an array to a pointer?  If so just pass on
811a9ac8606Spatrick         // the decayed value.
812a9ac8606Spatrick         if (CastTy->isPointerType() || CastTy->isReferenceType()) {
813a9ac8606Spatrick           // We will always decay to a pointer.
814a9ac8606Spatrick           QualType ElemTy = ArrayTy->getElementType();
815*12c85518Srobert           return VB.getStateManager().ArrayToPointer(V, ElemTy);
816a9ac8606Spatrick         }
817a9ac8606Spatrick         // Are we casting from an array to an integer?  If so, cast the decayed
818a9ac8606Spatrick         // pointer value to an integer.
819a9ac8606Spatrick         assert(CastTy->isIntegralOrEnumerationType());
820a9ac8606Spatrick       }
821a9ac8606Spatrick 
822a9ac8606Spatrick       // Other pointer to pointer.
823a9ac8606Spatrick       assert(Loc::isLocType(OriginalTy) || OriginalTy->isFunctionType() ||
824a9ac8606Spatrick              CastTy->isReferenceType());
825e5dd7070Spatrick 
826e5dd7070Spatrick       // We get a symbolic function pointer for a dereference of a function
827e5dd7070Spatrick       // pointer, but it is of function type. Example:
828e5dd7070Spatrick 
829e5dd7070Spatrick       //  struct FPRec {
830e5dd7070Spatrick       //    void (*my_func)(int * x);
831e5dd7070Spatrick       //  };
832e5dd7070Spatrick       //
833e5dd7070Spatrick       //  int bar(int x);
834e5dd7070Spatrick       //
835e5dd7070Spatrick       //  int f1_a(struct FPRec* foo) {
836e5dd7070Spatrick       //    int x;
837e5dd7070Spatrick       //    (*foo->my_func)(&x);
838e5dd7070Spatrick       //    return bar(x)+1; // no-warning
839e5dd7070Spatrick       //  }
840e5dd7070Spatrick 
841a9ac8606Spatrick       // Get the result of casting a region to a different type.
842a9ac8606Spatrick       const MemRegion *R = V.getRegion();
843*12c85518Srobert       if (auto OptMemRegV = VB.getCastedMemRegionVal(R, CastTy))
844a9ac8606Spatrick         return *OptMemRegV;
845a9ac8606Spatrick     }
846e5dd7070Spatrick 
847a9ac8606Spatrick     // Pointer to whatever else.
848a9ac8606Spatrick     // FIXME: There can be gross cases where one casts the result of a
849a9ac8606Spatrick     // function (that returns a pointer) to some other value that happens to
850a9ac8606Spatrick     // fit within that pointer value.  We currently have no good way to model
851a9ac8606Spatrick     // such operations.  When this happens, the underlying operation is that
852a9ac8606Spatrick     // the caller is reasoning about bits.  Conceptually we are layering a
853a9ac8606Spatrick     // "view" of a location on top of those bits.  Perhaps we need to be more
854a9ac8606Spatrick     // lazy about mutual possible views, even on an SVal?  This may be
855a9ac8606Spatrick     // necessary for bit-level reasoning as well.
856a9ac8606Spatrick     return UnknownVal();
857a9ac8606Spatrick   }
VisitNonLocCompoundVal(nonloc::CompoundVal V)858*12c85518Srobert   SVal VisitNonLocCompoundVal(nonloc::CompoundVal V) {
859a9ac8606Spatrick     // Compound to whatever.
860a9ac8606Spatrick     return UnknownVal();
861a9ac8606Spatrick   }
VisitNonLocConcreteInt(nonloc::ConcreteInt V)862*12c85518Srobert   SVal VisitNonLocConcreteInt(nonloc::ConcreteInt V) {
863*12c85518Srobert     auto CastedValue = [V, this]() {
864a9ac8606Spatrick       llvm::APSInt Value = V.getValue();
865*12c85518Srobert       VB.getBasicValueFactory().getAPSIntType(CastTy).apply(Value);
866a9ac8606Spatrick       return Value;
867a9ac8606Spatrick     };
868a9ac8606Spatrick 
869a9ac8606Spatrick     // Integer to bool.
870a9ac8606Spatrick     if (CastTy->isBooleanType())
871*12c85518Srobert       return VB.makeTruthVal(V.getValue().getBoolValue(), CastTy);
872a9ac8606Spatrick 
873a9ac8606Spatrick     // Integer to pointer.
874a9ac8606Spatrick     if (CastTy->isIntegralOrEnumerationType())
875*12c85518Srobert       return VB.makeIntVal(CastedValue());
876a9ac8606Spatrick 
877a9ac8606Spatrick     // Integer to pointer.
878a9ac8606Spatrick     if (Loc::isLocType(CastTy))
879*12c85518Srobert       return VB.makeIntLocVal(CastedValue());
880a9ac8606Spatrick 
881a9ac8606Spatrick     // Pointer to whatever else.
882a9ac8606Spatrick     return UnknownVal();
883a9ac8606Spatrick   }
VisitNonLocLazyCompoundVal(nonloc::LazyCompoundVal V)884*12c85518Srobert   SVal VisitNonLocLazyCompoundVal(nonloc::LazyCompoundVal V) {
885*12c85518Srobert     // LazyCompound to whatever.
886a9ac8606Spatrick     return UnknownVal();
887a9ac8606Spatrick   }
VisitNonLocLocAsInteger(nonloc::LocAsInteger V)888*12c85518Srobert   SVal VisitNonLocLocAsInteger(nonloc::LocAsInteger V) {
889a9ac8606Spatrick     Loc L = V.getLoc();
890a9ac8606Spatrick 
891a9ac8606Spatrick     // Pointer as integer to bool.
892a9ac8606Spatrick     if (CastTy->isBooleanType())
893a9ac8606Spatrick       // Pass to Loc function.
894*12c85518Srobert       return Visit(L);
895a9ac8606Spatrick 
896a9ac8606Spatrick     const bool IsUnknownOriginalType = OriginalTy.isNull();
897a9ac8606Spatrick     // Pointer as integer to pointer.
898a9ac8606Spatrick     if (!IsUnknownOriginalType && Loc::isLocType(CastTy) &&
899a9ac8606Spatrick         OriginalTy->isIntegralOrEnumerationType()) {
900a9ac8606Spatrick       if (const MemRegion *R = L.getAsRegion())
901*12c85518Srobert         if (auto OptMemRegV = VB.getCastedMemRegionVal(R, CastTy))
902a9ac8606Spatrick           return *OptMemRegV;
903a9ac8606Spatrick       return L;
904a9ac8606Spatrick     }
905a9ac8606Spatrick 
906a9ac8606Spatrick     // Pointer as integer with region to integer/pointer.
907a9ac8606Spatrick     const MemRegion *R = L.getAsRegion();
908a9ac8606Spatrick     if (!IsUnknownOriginalType && R) {
909a9ac8606Spatrick       if (CastTy->isIntegralOrEnumerationType())
910*12c85518Srobert         return VisitLocMemRegionVal(loc::MemRegionVal(R));
911a9ac8606Spatrick 
912a9ac8606Spatrick       if (Loc::isLocType(CastTy)) {
913a9ac8606Spatrick         assert(Loc::isLocType(OriginalTy) || OriginalTy->isFunctionType() ||
914a9ac8606Spatrick                CastTy->isReferenceType());
915e5dd7070Spatrick         // Delegate to store manager to get the result of casting a region to a
916e5dd7070Spatrick         // different type. If the MemRegion* returned is NULL, this expression
917e5dd7070Spatrick         // Evaluates to UnknownVal.
918*12c85518Srobert         if (auto OptMemRegV = VB.getCastedMemRegionVal(R, CastTy))
919a9ac8606Spatrick           return *OptMemRegV;
920a9ac8606Spatrick       }
921a9ac8606Spatrick     } else {
922a9ac8606Spatrick       if (Loc::isLocType(CastTy)) {
923a9ac8606Spatrick         if (IsUnknownOriginalType)
924*12c85518Srobert           return VisitLocMemRegionVal(loc::MemRegionVal(R));
925a9ac8606Spatrick         return L;
926e5dd7070Spatrick       }
927e5dd7070Spatrick 
928a9ac8606Spatrick       SymbolRef SE = nullptr;
929a9ac8606Spatrick       if (R) {
930a9ac8606Spatrick         if (const SymbolicRegion *SR =
931a9ac8606Spatrick                 dyn_cast<SymbolicRegion>(R->StripCasts())) {
932a9ac8606Spatrick           SE = SR->getSymbol();
933a9ac8606Spatrick         }
934a9ac8606Spatrick       }
935a9ac8606Spatrick 
936a9ac8606Spatrick       if (!CastTy->isFloatingType() || !SE || SE->getType()->isFloatingType()) {
937a9ac8606Spatrick         // FIXME: Correctly support promotions/truncations.
938a9ac8606Spatrick         const unsigned CastSize = Context.getIntWidth(CastTy);
939a9ac8606Spatrick         if (CastSize == V.getNumBits())
940a9ac8606Spatrick           return V;
941a9ac8606Spatrick 
942*12c85518Srobert         return VB.makeLocAsInteger(L, CastSize);
943a9ac8606Spatrick       }
944a9ac8606Spatrick     }
945a9ac8606Spatrick 
946a9ac8606Spatrick     // Pointer as integer to whatever else.
947a9ac8606Spatrick     return UnknownVal();
948a9ac8606Spatrick   }
VisitNonLocSymbolVal(nonloc::SymbolVal V)949*12c85518Srobert   SVal VisitNonLocSymbolVal(nonloc::SymbolVal V) {
950a9ac8606Spatrick     SymbolRef SE = V.getSymbol();
951a9ac8606Spatrick 
952a9ac8606Spatrick     const bool IsUnknownOriginalType = OriginalTy.isNull();
953a9ac8606Spatrick     // Symbol to bool.
954a9ac8606Spatrick     if (!IsUnknownOriginalType && CastTy->isBooleanType()) {
955a9ac8606Spatrick       // Non-float to bool.
956a9ac8606Spatrick       if (Loc::isLocType(OriginalTy) ||
957a9ac8606Spatrick           OriginalTy->isIntegralOrEnumerationType() ||
958a9ac8606Spatrick           OriginalTy->isMemberPointerType()) {
959*12c85518Srobert         BasicValueFactory &BVF = VB.getBasicValueFactory();
960*12c85518Srobert         return VB.makeNonLoc(SE, BO_NE, BVF.getValue(0, SE->getType()), CastTy);
961a9ac8606Spatrick       }
962a9ac8606Spatrick     } else {
963a9ac8606Spatrick       // Symbol to integer, float.
964a9ac8606Spatrick       QualType T = Context.getCanonicalType(SE->getType());
965*12c85518Srobert 
966*12c85518Srobert       // Produce SymbolCast if CastTy and T are different integers.
967*12c85518Srobert       // NOTE: In the end the type of SymbolCast shall be equal to CastTy.
968*12c85518Srobert       if (T->isIntegralOrUnscopedEnumerationType() &&
969*12c85518Srobert           CastTy->isIntegralOrUnscopedEnumerationType()) {
970*12c85518Srobert         AnalyzerOptions &Opts = VB.getStateManager()
971*12c85518Srobert                                     .getOwningEngine()
972*12c85518Srobert                                     .getAnalysisManager()
973*12c85518Srobert                                     .getAnalyzerOptions();
974*12c85518Srobert         // If appropriate option is disabled, ignore the cast.
975*12c85518Srobert         // NOTE: ShouldSupportSymbolicIntegerCasts is `false` by default.
976*12c85518Srobert         if (!Opts.ShouldSupportSymbolicIntegerCasts)
977a9ac8606Spatrick           return V;
978*12c85518Srobert         return simplifySymbolCast(V, CastTy);
979*12c85518Srobert       }
980a9ac8606Spatrick       if (!Loc::isLocType(CastTy))
981a9ac8606Spatrick         if (!IsUnknownOriginalType || !CastTy->isFloatingType() ||
982a9ac8606Spatrick             T->isFloatingType())
983*12c85518Srobert           return VB.makeNonLoc(SE, T, CastTy);
984a9ac8606Spatrick     }
985a9ac8606Spatrick 
986a9ac8606Spatrick     // Symbol to pointer and whatever else.
987a9ac8606Spatrick     return UnknownVal();
988a9ac8606Spatrick   }
VisitNonLocPointerToMember(nonloc::PointerToMember V)989*12c85518Srobert   SVal VisitNonLocPointerToMember(nonloc::PointerToMember V) {
990a9ac8606Spatrick     // Member pointer to whatever.
991a9ac8606Spatrick     return V;
992e5dd7070Spatrick   }
993*12c85518Srobert 
994*12c85518Srobert   /// Reduce cast expression by removing redundant intermediate casts.
995*12c85518Srobert   /// E.g.
996*12c85518Srobert   /// - (char)(short)(int x) -> (char)(int x)
997*12c85518Srobert   /// - (int)(int x) -> int x
998*12c85518Srobert   ///
999*12c85518Srobert   /// \param V -- SymbolVal, which pressumably contains SymbolCast or any symbol
1000*12c85518Srobert   /// that is applicable for cast operation.
1001*12c85518Srobert   /// \param CastTy -- QualType, which `V` shall be cast to.
1002*12c85518Srobert   /// \return SVal with simplified cast expression.
1003*12c85518Srobert   /// \note: Currently only support integral casts.
simplifySymbolCast(nonloc::SymbolVal V,QualType CastTy)1004*12c85518Srobert   nonloc::SymbolVal simplifySymbolCast(nonloc::SymbolVal V, QualType CastTy) {
1005*12c85518Srobert     // We use seven conditions to recognize a simplification case.
1006*12c85518Srobert     // For the clarity let `CastTy` be `C`, SE->getType() - `T`, root type -
1007*12c85518Srobert     // `R`, prefix `u` for unsigned, `s` for signed, no prefix - any sign: E.g.
1008*12c85518Srobert     // (char)(short)(uint x)
1009*12c85518Srobert     //      ( sC )( sT  )( uR  x)
1010*12c85518Srobert     //
1011*12c85518Srobert     // C === R (the same type)
1012*12c85518Srobert     //  (char)(char x) -> (char x)
1013*12c85518Srobert     //  (long)(long x) -> (long x)
1014*12c85518Srobert     // Note: Comparisons operators below are for bit width.
1015*12c85518Srobert     // C == T
1016*12c85518Srobert     //  (short)(short)(int x) -> (short)(int x)
1017*12c85518Srobert     //  (int)(long)(char x) -> (int)(char x) (sizeof(long) == sizeof(int))
1018*12c85518Srobert     //  (long)(ullong)(char x) -> (long)(char x) (sizeof(long) ==
1019*12c85518Srobert     //  sizeof(ullong))
1020*12c85518Srobert     // C < T
1021*12c85518Srobert     //  (short)(int)(char x) -> (short)(char x)
1022*12c85518Srobert     //  (char)(int)(short x) -> (char)(short x)
1023*12c85518Srobert     //  (short)(int)(short x) -> (short x)
1024*12c85518Srobert     // C > T > uR
1025*12c85518Srobert     //  (int)(short)(uchar x) -> (int)(uchar x)
1026*12c85518Srobert     //  (uint)(short)(uchar x) -> (uint)(uchar x)
1027*12c85518Srobert     //  (int)(ushort)(uchar x) -> (int)(uchar x)
1028*12c85518Srobert     // C > sT > sR
1029*12c85518Srobert     //  (int)(short)(char x) -> (int)(char x)
1030*12c85518Srobert     //  (uint)(short)(char x) -> (uint)(char x)
1031*12c85518Srobert     // C > sT == sR
1032*12c85518Srobert     //  (int)(char)(char x) -> (int)(char x)
1033*12c85518Srobert     //  (uint)(short)(short x) -> (uint)(short x)
1034*12c85518Srobert     // C > uT == uR
1035*12c85518Srobert     //  (int)(uchar)(uchar x) -> (int)(uchar x)
1036*12c85518Srobert     //  (uint)(ushort)(ushort x) -> (uint)(ushort x)
1037*12c85518Srobert     //  (llong)(ulong)(uint x) -> (llong)(uint x) (sizeof(ulong) ==
1038*12c85518Srobert     //  sizeof(uint))
1039*12c85518Srobert 
1040*12c85518Srobert     SymbolRef SE = V.getSymbol();
1041*12c85518Srobert     QualType T = Context.getCanonicalType(SE->getType());
1042*12c85518Srobert 
1043*12c85518Srobert     if (T == CastTy)
1044*12c85518Srobert       return V;
1045*12c85518Srobert 
1046*12c85518Srobert     if (!isa<SymbolCast>(SE))
1047*12c85518Srobert       return VB.makeNonLoc(SE, T, CastTy);
1048*12c85518Srobert 
1049*12c85518Srobert     SymbolRef RootSym = cast<SymbolCast>(SE)->getOperand();
1050*12c85518Srobert     QualType RT = RootSym->getType().getCanonicalType();
1051*12c85518Srobert 
1052*12c85518Srobert     // FIXME support simplification from non-integers.
1053*12c85518Srobert     if (!RT->isIntegralOrEnumerationType())
1054*12c85518Srobert       return VB.makeNonLoc(SE, T, CastTy);
1055*12c85518Srobert 
1056*12c85518Srobert     BasicValueFactory &BVF = VB.getBasicValueFactory();
1057*12c85518Srobert     APSIntType CTy = BVF.getAPSIntType(CastTy);
1058*12c85518Srobert     APSIntType TTy = BVF.getAPSIntType(T);
1059*12c85518Srobert 
1060*12c85518Srobert     const auto WC = CTy.getBitWidth();
1061*12c85518Srobert     const auto WT = TTy.getBitWidth();
1062*12c85518Srobert 
1063*12c85518Srobert     if (WC <= WT) {
1064*12c85518Srobert       const bool isSameType = (RT == CastTy);
1065*12c85518Srobert       if (isSameType)
1066*12c85518Srobert         return nonloc::SymbolVal(RootSym);
1067*12c85518Srobert       return VB.makeNonLoc(RootSym, RT, CastTy);
1068*12c85518Srobert     }
1069*12c85518Srobert 
1070*12c85518Srobert     APSIntType RTy = BVF.getAPSIntType(RT);
1071*12c85518Srobert     const auto WR = RTy.getBitWidth();
1072*12c85518Srobert     const bool UT = TTy.isUnsigned();
1073*12c85518Srobert     const bool UR = RTy.isUnsigned();
1074*12c85518Srobert 
1075*12c85518Srobert     if (((WT > WR) && (UR || !UT)) || ((WT == WR) && (UT == UR)))
1076*12c85518Srobert       return VB.makeNonLoc(RootSym, RT, CastTy);
1077*12c85518Srobert 
1078*12c85518Srobert     return VB.makeNonLoc(SE, T, CastTy);
1079*12c85518Srobert   }
1080*12c85518Srobert };
1081*12c85518Srobert } // end anonymous namespace
1082*12c85518Srobert 
1083*12c85518Srobert /// Cast a given SVal to another SVal using given QualType's.
1084*12c85518Srobert /// \param V -- SVal that should be casted.
1085*12c85518Srobert /// \param CastTy -- QualType that V should be casted according to.
1086*12c85518Srobert /// \param OriginalTy -- QualType which is associated to V. It provides
1087*12c85518Srobert /// additional information about what type the cast performs from.
1088*12c85518Srobert /// \returns the most appropriate casted SVal.
1089*12c85518Srobert /// Note: Many cases don't use an exact OriginalTy. It can be extracted
1090*12c85518Srobert /// from SVal or the cast can performs unconditionaly. Always pass OriginalTy!
1091*12c85518Srobert /// It can be crucial in certain cases and generates different results.
1092*12c85518Srobert /// FIXME: If `OriginalTy.isNull()` is true, then cast performs based on CastTy
1093*12c85518Srobert /// only. This behavior is uncertain and should be improved.
evalCast(SVal V,QualType CastTy,QualType OriginalTy)1094*12c85518Srobert SVal SValBuilder::evalCast(SVal V, QualType CastTy, QualType OriginalTy) {
1095*12c85518Srobert   EvalCastVisitor TRV{*this, CastTy, OriginalTy};
1096*12c85518Srobert   return TRV.Visit(V);
1097*12c85518Srobert }
1098