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