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