Bug Summary

File:tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
Warning:line 439, column 10
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name SValBuilder.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mthread-model posix -relaxed-aliasing -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-9/lib/clang/9.0.0 -D CLANG_VENDOR="Debian " -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-9~svn362543/build-llvm/tools/clang/lib/StaticAnalyzer/Core -I /build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core -I /build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include -I /build/llvm-toolchain-snapshot-9~svn362543/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-9~svn362543/build-llvm/include -I /build/llvm-toolchain-snapshot-9~svn362543/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/include/clang/9.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-9/lib/clang/9.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-9~svn362543/build-llvm/tools/clang/lib/StaticAnalyzer/Core -fdebug-prefix-map=/build/llvm-toolchain-snapshot-9~svn362543=. -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -stack-protector 2 -fobjc-runtime=gcc -fno-common -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2019-06-05-060531-1271-1 -x c++ /build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp -faddrsig

/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp

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/Basic/LLVM.h"
23#include "clang/Analysis/AnalysisDeclContext.h"
24#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
25#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
26#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
27#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
28#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
29#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
30#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
31#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
32#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
33#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
34#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
35#include "llvm/ADT/APSInt.h"
36#include "llvm/ADT/None.h"
37#include "llvm/ADT/Optional.h"
38#include "llvm/Support/Casting.h"
39#include "llvm/Support/Compiler.h"
40#include <cassert>
41#include <tuple>
42
43using namespace clang;
44using namespace ento;
45
46//===----------------------------------------------------------------------===//
47// Basic SVal creation.
48//===----------------------------------------------------------------------===//
49
50void SValBuilder::anchor() {}
51
52DefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType type) {
53 if (Loc::isLocType(type))
54 return makeNull();
55
56 if (type->isIntegralOrEnumerationType())
57 return makeIntVal(0, type);
58
59 if (type->isArrayType() || type->isRecordType() || type->isVectorType() ||
60 type->isAnyComplexType())
61 return makeCompoundVal(type, BasicVals.getEmptySValList());
62
63 // FIXME: Handle floats.
64 return UnknownVal();
65}
66
67NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
68 const llvm::APSInt& rhs, QualType type) {
69 // The Environment ensures we always get a persistent APSInt in
70 // BasicValueFactory, so we don't need to get the APSInt from
71 // BasicValueFactory again.
72 assert(lhs)((lhs) ? static_cast<void> (0) : __assert_fail ("lhs", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 72, __PRETTY_FUNCTION__))
;
73 assert(!Loc::isLocType(type))((!Loc::isLocType(type)) ? static_cast<void> (0) : __assert_fail
("!Loc::isLocType(type)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 73, __PRETTY_FUNCTION__))
;
74 return nonloc::SymbolVal(SymMgr.getSymIntExpr(lhs, op, rhs, type));
75}
76
77NonLoc SValBuilder::makeNonLoc(const llvm::APSInt& lhs,
78 BinaryOperator::Opcode op, const SymExpr *rhs,
79 QualType type) {
80 assert(rhs)((rhs) ? static_cast<void> (0) : __assert_fail ("rhs", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 80, __PRETTY_FUNCTION__))
;
81 assert(!Loc::isLocType(type))((!Loc::isLocType(type)) ? static_cast<void> (0) : __assert_fail
("!Loc::isLocType(type)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 81, __PRETTY_FUNCTION__))
;
82 return nonloc::SymbolVal(SymMgr.getIntSymExpr(lhs, op, rhs, type));
83}
84
85NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
86 const SymExpr *rhs, QualType type) {
87 assert(lhs && rhs)((lhs && rhs) ? static_cast<void> (0) : __assert_fail
("lhs && rhs", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 87, __PRETTY_FUNCTION__))
;
88 assert(!Loc::isLocType(type))((!Loc::isLocType(type)) ? static_cast<void> (0) : __assert_fail
("!Loc::isLocType(type)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 88, __PRETTY_FUNCTION__))
;
89 return nonloc::SymbolVal(SymMgr.getSymSymExpr(lhs, op, rhs, type));
90}
91
92NonLoc SValBuilder::makeNonLoc(const SymExpr *operand,
93 QualType fromTy, QualType toTy) {
94 assert(operand)((operand) ? static_cast<void> (0) : __assert_fail ("operand"
, "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 94, __PRETTY_FUNCTION__))
;
95 assert(!Loc::isLocType(toTy))((!Loc::isLocType(toTy)) ? static_cast<void> (0) : __assert_fail
("!Loc::isLocType(toTy)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 95, __PRETTY_FUNCTION__))
;
96 return nonloc::SymbolVal(SymMgr.getCastSymbol(operand, fromTy, toTy));
97}
98
99SVal SValBuilder::convertToArrayIndex(SVal val) {
100 if (val.isUnknownOrUndef())
101 return val;
102
103 // Common case: we have an appropriately sized integer.
104 if (Optional<nonloc::ConcreteInt> CI = val.getAs<nonloc::ConcreteInt>()) {
105 const llvm::APSInt& I = CI->getValue();
106 if (I.getBitWidth() == ArrayIndexWidth && I.isSigned())
107 return val;
108 }
109
110 return evalCastFromNonLoc(val.castAs<NonLoc>(), ArrayIndexTy);
111}
112
113nonloc::ConcreteInt SValBuilder::makeBoolVal(const CXXBoolLiteralExpr *boolean){
114 return makeTruthVal(boolean->getValue());
115}
116
117DefinedOrUnknownSVal
118SValBuilder::getRegionValueSymbolVal(const TypedValueRegion *region) {
119 QualType T = region->getValueType();
120
121 if (T->isNullPtrType())
122 return makeZeroVal(T);
123
124 if (!SymbolManager::canSymbolicate(T))
125 return UnknownVal();
126
127 SymbolRef sym = SymMgr.getRegionValueSymbol(region);
128
129 if (Loc::isLocType(T))
130 return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
131
132 return nonloc::SymbolVal(sym);
133}
134
135DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *SymbolTag,
136 const Expr *Ex,
137 const LocationContext *LCtx,
138 unsigned Count) {
139 QualType T = Ex->getType();
140
141 if (T->isNullPtrType())
142 return makeZeroVal(T);
143
144 // Compute the type of the result. If the expression is not an R-value, the
145 // result should be a location.
146 QualType ExType = Ex->getType();
147 if (Ex->isGLValue())
148 T = LCtx->getAnalysisDeclContext()->getASTContext().getPointerType(ExType);
149
150 return conjureSymbolVal(SymbolTag, Ex, LCtx, T, Count);
151}
152
153DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *symbolTag,
154 const Expr *expr,
155 const LocationContext *LCtx,
156 QualType type,
157 unsigned count) {
158 if (type->isNullPtrType())
159 return makeZeroVal(type);
160
161 if (!SymbolManager::canSymbolicate(type))
162 return UnknownVal();
163
164 SymbolRef sym = SymMgr.conjureSymbol(expr, LCtx, type, count, symbolTag);
165
166 if (Loc::isLocType(type))
167 return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
168
169 return nonloc::SymbolVal(sym);
170}
171
172DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const Stmt *stmt,
173 const LocationContext *LCtx,
174 QualType type,
175 unsigned visitCount) {
176 if (type->isNullPtrType())
177 return makeZeroVal(type);
178
179 if (!SymbolManager::canSymbolicate(type))
180 return UnknownVal();
181
182 SymbolRef sym = SymMgr.conjureSymbol(stmt, LCtx, type, visitCount);
183
184 if (Loc::isLocType(type))
185 return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
186
187 return nonloc::SymbolVal(sym);
188}
189
190DefinedOrUnknownSVal
191SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
192 const LocationContext *LCtx,
193 unsigned VisitCount) {
194 QualType T = E->getType();
195 assert(Loc::isLocType(T))((Loc::isLocType(T)) ? static_cast<void> (0) : __assert_fail
("Loc::isLocType(T)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 195, __PRETTY_FUNCTION__))
;
196 assert(SymbolManager::canSymbolicate(T))((SymbolManager::canSymbolicate(T)) ? static_cast<void>
(0) : __assert_fail ("SymbolManager::canSymbolicate(T)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 196, __PRETTY_FUNCTION__))
;
197 if (T->isNullPtrType())
198 return makeZeroVal(T);
199
200 SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, T, VisitCount);
201 return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym));
202}
203
204DefinedSVal SValBuilder::getMetadataSymbolVal(const void *symbolTag,
205 const MemRegion *region,
206 const Expr *expr, QualType type,
207 const LocationContext *LCtx,
208 unsigned count) {
209 assert(SymbolManager::canSymbolicate(type) && "Invalid metadata symbol type")((SymbolManager::canSymbolicate(type) && "Invalid metadata symbol type"
) ? static_cast<void> (0) : __assert_fail ("SymbolManager::canSymbolicate(type) && \"Invalid metadata symbol type\""
, "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 209, __PRETTY_FUNCTION__))
;
210
211 SymbolRef sym =
212 SymMgr.getMetadataSymbol(region, expr, type, LCtx, count, symbolTag);
213
214 if (Loc::isLocType(type))
215 return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
216
217 return nonloc::SymbolVal(sym);
218}
219
220DefinedOrUnknownSVal
221SValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
222 const TypedValueRegion *region) {
223 QualType T = region->getValueType();
224
225 if (T->isNullPtrType())
226 return makeZeroVal(T);
227
228 if (!SymbolManager::canSymbolicate(T))
229 return UnknownVal();
230
231 SymbolRef sym = SymMgr.getDerivedSymbol(parentSymbol, region);
232
233 if (Loc::isLocType(T))
234 return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
235
236 return nonloc::SymbolVal(sym);
237}
238
239DefinedSVal SValBuilder::getMemberPointer(const DeclaratorDecl *DD) {
240 assert(!DD || isa<CXXMethodDecl>(DD) || isa<FieldDecl>(DD))((!DD || isa<CXXMethodDecl>(DD) || isa<FieldDecl>
(DD)) ? static_cast<void> (0) : __assert_fail ("!DD || isa<CXXMethodDecl>(DD) || isa<FieldDecl>(DD)"
, "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 240, __PRETTY_FUNCTION__))
;
241
242 if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(DD)) {
243 // Sema treats pointers to static member functions as have function pointer
244 // type, so return a function pointer for the method.
245 // We don't need to play a similar trick for static member fields
246 // because these are represented as plain VarDecls and not FieldDecls
247 // in the AST.
248 if (MD->isStatic())
249 return getFunctionPointer(MD);
250 }
251
252 return nonloc::PointerToMember(DD);
253}
254
255DefinedSVal SValBuilder::getFunctionPointer(const FunctionDecl *func) {
256 return loc::MemRegionVal(MemMgr.getFunctionCodeRegion(func));
257}
258
259DefinedSVal SValBuilder::getBlockPointer(const BlockDecl *block,
260 CanQualType locTy,
261 const LocationContext *locContext,
262 unsigned blockCount) {
263 const BlockCodeRegion *BC =
264 MemMgr.getBlockCodeRegion(block, locTy, locContext->getAnalysisDeclContext());
265 const BlockDataRegion *BD = MemMgr.getBlockDataRegion(BC, locContext,
266 blockCount);
267 return loc::MemRegionVal(BD);
268}
269
270/// Return a memory region for the 'this' object reference.
271loc::MemRegionVal SValBuilder::getCXXThis(const CXXMethodDecl *D,
272 const StackFrameContext *SFC) {
273 return loc::MemRegionVal(
274 getRegionManager().getCXXThisRegion(D->getThisType(), SFC));
275}
276
277/// Return a memory region for the 'this' object reference.
278loc::MemRegionVal SValBuilder::getCXXThis(const CXXRecordDecl *D,
279 const StackFrameContext *SFC) {
280 const Type *T = D->getTypeForDecl();
281 QualType PT = getContext().getPointerType(QualType(T, 0));
282 return loc::MemRegionVal(getRegionManager().getCXXThisRegion(PT, SFC));
283}
284
285Optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
286 E = E->IgnoreParens();
287
288 switch (E->getStmtClass()) {
289 // Handle expressions that we treat differently from the AST's constant
290 // evaluator.
291 case Stmt::AddrLabelExprClass:
292 return makeLoc(cast<AddrLabelExpr>(E));
293
294 case Stmt::CXXScalarValueInitExprClass:
295 case Stmt::ImplicitValueInitExprClass:
296 return makeZeroVal(E->getType());
297
298 case Stmt::ObjCStringLiteralClass: {
299 const auto *SL = cast<ObjCStringLiteral>(E);
300 return makeLoc(getRegionManager().getObjCStringRegion(SL));
301 }
302
303 case Stmt::StringLiteralClass: {
304 const auto *SL = cast<StringLiteral>(E);
305 return makeLoc(getRegionManager().getStringRegion(SL));
306 }
307
308 // Fast-path some expressions to avoid the overhead of going through the AST's
309 // constant evaluator
310 case Stmt::CharacterLiteralClass: {
311 const auto *C = cast<CharacterLiteral>(E);
312 return makeIntVal(C->getValue(), C->getType());
313 }
314
315 case Stmt::CXXBoolLiteralExprClass:
316 return makeBoolVal(cast<CXXBoolLiteralExpr>(E));
317
318 case Stmt::TypeTraitExprClass: {
319 const auto *TE = cast<TypeTraitExpr>(E);
320 return makeTruthVal(TE->getValue(), TE->getType());
321 }
322
323 case Stmt::IntegerLiteralClass:
324 return makeIntVal(cast<IntegerLiteral>(E));
325
326 case Stmt::ObjCBoolLiteralExprClass:
327 return makeBoolVal(cast<ObjCBoolLiteralExpr>(E));
328
329 case Stmt::CXXNullPtrLiteralExprClass:
330 return makeNull();
331
332 case Stmt::CStyleCastExprClass:
333 case Stmt::CXXFunctionalCastExprClass:
334 case Stmt::CXXConstCastExprClass:
335 case Stmt::CXXReinterpretCastExprClass:
336 case Stmt::CXXStaticCastExprClass:
337 case Stmt::ImplicitCastExprClass: {
338 const auto *CE = cast<CastExpr>(E);
339 switch (CE->getCastKind()) {
340 default:
341 break;
342 case CK_ArrayToPointerDecay:
343 case CK_IntegralToPointer:
344 case CK_NoOp:
345 case CK_BitCast: {
346 const Expr *SE = CE->getSubExpr();
347 Optional<SVal> Val = getConstantVal(SE);
348 if (!Val)
349 return None;
350 return evalCast(*Val, CE->getType(), SE->getType());
351 }
352 }
353 // FALLTHROUGH
354 LLVM_FALLTHROUGH[[clang::fallthrough]];
355 }
356
357 // If we don't have a special case, fall back to the AST's constant evaluator.
358 default: {
359 // Don't try to come up with a value for materialized temporaries.
360 if (E->isGLValue())
361 return None;
362
363 ASTContext &Ctx = getContext();
364 Expr::EvalResult Result;
365 if (E->EvaluateAsInt(Result, Ctx))
366 return makeIntVal(Result.Val.getInt());
367
368 if (Loc::isLocType(E->getType()))
369 if (E->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))
370 return makeNull();
371
372 return None;
373 }
374 }
375}
376
377SVal SValBuilder::makeSymExprValNN(BinaryOperator::Opcode Op,
378 NonLoc LHS, NonLoc RHS,
379 QualType ResultTy) {
380 const SymExpr *symLHS = LHS.getAsSymExpr();
381 const SymExpr *symRHS = RHS.getAsSymExpr();
382
383 // TODO: When the Max Complexity is reached, we should conjure a symbol
384 // instead of generating an Unknown value and propagate the taint info to it.
385 const unsigned MaxComp = StateMgr.getOwningEngine()
386 .getAnalysisManager()
387 .options.MaxSymbolComplexity;
388
389 if (symLHS && symRHS &&
390 (symLHS->computeComplexity() + symRHS->computeComplexity()) < MaxComp)
391 return makeNonLoc(symLHS, Op, symRHS, ResultTy);
392
393 if (symLHS && symLHS->computeComplexity() < MaxComp)
394 if (Optional<nonloc::ConcreteInt> rInt = RHS.getAs<nonloc::ConcreteInt>())
395 return makeNonLoc(symLHS, Op, rInt->getValue(), ResultTy);
396
397 if (symRHS && symRHS->computeComplexity() < MaxComp)
398 if (Optional<nonloc::ConcreteInt> lInt = LHS.getAs<nonloc::ConcreteInt>())
399 return makeNonLoc(lInt->getValue(), Op, symRHS, ResultTy);
400
401 return UnknownVal();
402}
403
404SVal SValBuilder::evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
405 SVal lhs, SVal rhs, QualType type) {
406 if (lhs.isUndef() || rhs.isUndef())
407 return UndefinedVal();
408
409 if (lhs.isUnknown() || rhs.isUnknown())
410 return UnknownVal();
411
412 if (lhs.getAs<nonloc::LazyCompoundVal>() ||
413 rhs.getAs<nonloc::LazyCompoundVal>()) {
414 return UnknownVal();
415 }
416
417 if (Optional<Loc> LV = lhs.getAs<Loc>()) {
418 if (Optional<Loc> RV = rhs.getAs<Loc>())
419 return evalBinOpLL(state, op, *LV, *RV, type);
420
421 return evalBinOpLN(state, op, *LV, rhs.castAs<NonLoc>(), type);
422 }
423
424 if (Optional<Loc> RV = rhs.getAs<Loc>()) {
425 // Support pointer arithmetic where the addend is on the left
426 // and the pointer on the right.
427 assert(op == BO_Add)((op == BO_Add) ? static_cast<void> (0) : __assert_fail
("op == BO_Add", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 427, __PRETTY_FUNCTION__))
;
428
429 // Commute the operands.
430 return evalBinOpLN(state, op, *RV, lhs.castAs<NonLoc>(), type);
431 }
432
433 return evalBinOpNN(state, op, lhs.castAs<NonLoc>(), rhs.castAs<NonLoc>(),
434 type);
435}
436
437ConditionTruthVal SValBuilder::areEqual(ProgramStateRef state, SVal lhs,
438 SVal rhs) {
439 return state->isNonNull(evalEQ(state, lhs, rhs));
1
Calling 'IntrusiveRefCntPtr::operator->'
3
Returning from 'IntrusiveRefCntPtr::operator->'
4
Called C++ object pointer is null
440}
441
442SVal SValBuilder::evalEQ(ProgramStateRef state, SVal lhs, SVal rhs) {
443 return evalBinOp(state, BO_EQ, lhs, rhs, getConditionType());
444}
445
446DefinedOrUnknownSVal SValBuilder::evalEQ(ProgramStateRef state,
447 DefinedOrUnknownSVal lhs,
448 DefinedOrUnknownSVal rhs) {
449 return evalEQ(state, static_cast<SVal>(lhs), static_cast<SVal>(rhs))
450 .castAs<DefinedOrUnknownSVal>();
451}
452
453/// Recursively check if the pointer types are equal modulo const, volatile,
454/// and restrict qualifiers. Also, assume that all types are similar to 'void'.
455/// Assumes the input types are canonical.
456static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy,
457 QualType FromTy) {
458 while (Context.UnwrapSimilarTypes(ToTy, FromTy)) {
459 Qualifiers Quals1, Quals2;
460 ToTy = Context.getUnqualifiedArrayType(ToTy, Quals1);
461 FromTy = Context.getUnqualifiedArrayType(FromTy, Quals2);
462
463 // Make sure that non-cvr-qualifiers the other qualifiers (e.g., address
464 // spaces) are identical.
465 Quals1.removeCVRQualifiers();
466 Quals2.removeCVRQualifiers();
467 if (Quals1 != Quals2)
468 return false;
469 }
470
471 // If we are casting to void, the 'From' value can be used to represent the
472 // 'To' value.
473 //
474 // FIXME: Doing this after unwrapping the types doesn't make any sense. A
475 // cast from 'int**' to 'void**' is not special in the way that a cast from
476 // 'int*' to 'void*' is.
477 if (ToTy->isVoidType())
478 return true;
479
480 if (ToTy != FromTy)
481 return false;
482
483 return true;
484}
485
486// Handles casts of type CK_IntegralCast.
487// At the moment, this function will redirect to evalCast, except when the range
488// of the original value is known to be greater than the max of the target type.
489SVal SValBuilder::evalIntegralCast(ProgramStateRef state, SVal val,
490 QualType castTy, QualType originalTy) {
491 // No truncations if target type is big enough.
492 if (getContext().getTypeSize(castTy) >= getContext().getTypeSize(originalTy))
493 return evalCast(val, castTy, originalTy);
494
495 const SymExpr *se = val.getAsSymbolicExpression();
496 if (!se) // Let evalCast handle non symbolic expressions.
497 return evalCast(val, castTy, originalTy);
498
499 // Find the maximum value of the target type.
500 APSIntType ToType(getContext().getTypeSize(castTy),
501 castTy->isUnsignedIntegerType());
502 llvm::APSInt ToTypeMax = ToType.getMaxValue();
503 NonLoc ToTypeMaxVal =
504 makeIntVal(ToTypeMax.isUnsigned() ? ToTypeMax.getZExtValue()
505 : ToTypeMax.getSExtValue(),
506 castTy)
507 .castAs<NonLoc>();
508 // Check the range of the symbol being casted against the maximum value of the
509 // target type.
510 NonLoc FromVal = val.castAs<NonLoc>();
511 QualType CmpTy = getConditionType();
512 NonLoc CompVal =
513 evalBinOpNN(state, BO_LE, FromVal, ToTypeMaxVal, CmpTy).castAs<NonLoc>();
514 ProgramStateRef IsNotTruncated, IsTruncated;
515 std::tie(IsNotTruncated, IsTruncated) = state->assume(CompVal);
516 if (!IsNotTruncated && IsTruncated) {
517 // Symbol is truncated so we evaluate it as a cast.
518 NonLoc CastVal = makeNonLoc(se, originalTy, castTy);
519 return CastVal;
520 }
521 return evalCast(val, castTy, originalTy);
522}
523
524// FIXME: should rewrite according to the cast kind.
525SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
526 castTy = Context.getCanonicalType(castTy);
527 originalTy = Context.getCanonicalType(originalTy);
528 if (val.isUnknownOrUndef() || castTy == originalTy)
529 return val;
530
531 if (castTy->isBooleanType()) {
532 if (val.isUnknownOrUndef())
533 return val;
534 if (val.isConstant())
535 return makeTruthVal(!val.isZeroConstant(), castTy);
536 if (!Loc::isLocType(originalTy) &&
537 !originalTy->isIntegralOrEnumerationType() &&
538 !originalTy->isMemberPointerType())
539 return UnknownVal();
540 if (SymbolRef Sym = val.getAsSymbol(true)) {
541 BasicValueFactory &BVF = getBasicValueFactory();
542 // FIXME: If we had a state here, we could see if the symbol is known to
543 // be zero, but we don't.
544 return makeNonLoc(Sym, BO_NE, BVF.getValue(0, Sym->getType()), castTy);
545 }
546 // Loc values are not always true, they could be weakly linked functions.
547 if (Optional<Loc> L = val.getAs<Loc>())
548 return evalCastFromLoc(*L, castTy);
549
550 Loc L = val.castAs<nonloc::LocAsInteger>().getLoc();
551 return evalCastFromLoc(L, castTy);
552 }
553
554 // For const casts, casts to void, just propagate the value.
555 if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType())
556 if (shouldBeModeledWithNoOp(Context, Context.getPointerType(castTy),
557 Context.getPointerType(originalTy)))
558 return val;
559
560 // Check for casts from pointers to integers.
561 if (castTy->isIntegralOrEnumerationType() && Loc::isLocType(originalTy))
562 return evalCastFromLoc(val.castAs<Loc>(), castTy);
563
564 // Check for casts from integers to pointers.
565 if (Loc::isLocType(castTy) && originalTy->isIntegralOrEnumerationType()) {
566 if (Optional<nonloc::LocAsInteger> LV = val.getAs<nonloc::LocAsInteger>()) {
567 if (const MemRegion *R = LV->getLoc().getAsRegion()) {
568 StoreManager &storeMgr = StateMgr.getStoreManager();
569 R = storeMgr.castRegion(R, castTy);
570 return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
571 }
572 return LV->getLoc();
573 }
574 return dispatchCast(val, castTy);
575 }
576
577 // Just pass through function and block pointers.
578 if (originalTy->isBlockPointerType() || originalTy->isFunctionPointerType()) {
579 assert(Loc::isLocType(castTy))((Loc::isLocType(castTy)) ? static_cast<void> (0) : __assert_fail
("Loc::isLocType(castTy)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 579, __PRETTY_FUNCTION__))
;
580 return val;
581 }
582
583 // Check for casts from array type to another type.
584 if (const auto *arrayT =
585 dyn_cast<ArrayType>(originalTy.getCanonicalType())) {
586 // We will always decay to a pointer.
587 QualType elemTy = arrayT->getElementType();
588 val = StateMgr.ArrayToPointer(val.castAs<Loc>(), elemTy);
589
590 // Are we casting from an array to a pointer? If so just pass on
591 // the decayed value.
592 if (castTy->isPointerType() || castTy->isReferenceType())
593 return val;
594
595 // Are we casting from an array to an integer? If so, cast the decayed
596 // pointer value to an integer.
597 assert(castTy->isIntegralOrEnumerationType())((castTy->isIntegralOrEnumerationType()) ? static_cast<
void> (0) : __assert_fail ("castTy->isIntegralOrEnumerationType()"
, "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 597, __PRETTY_FUNCTION__))
;
598
599 // FIXME: Keep these here for now in case we decide soon that we
600 // need the original decayed type.
601 // QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
602 // QualType pointerTy = C.getPointerType(elemTy);
603 return evalCastFromLoc(val.castAs<Loc>(), castTy);
604 }
605
606 // Check for casts from a region to a specific type.
607 if (const MemRegion *R = val.getAsRegion()) {
608 // Handle other casts of locations to integers.
609 if (castTy->isIntegralOrEnumerationType())
610 return evalCastFromLoc(loc::MemRegionVal(R), castTy);
611
612 // FIXME: We should handle the case where we strip off view layers to get
613 // to a desugared type.
614 if (!Loc::isLocType(castTy)) {
615 // FIXME: There can be gross cases where one casts the result of a function
616 // (that returns a pointer) to some other value that happens to fit
617 // within that pointer value. We currently have no good way to
618 // model such operations. When this happens, the underlying operation
619 // is that the caller is reasoning about bits. Conceptually we are
620 // layering a "view" of a location on top of those bits. Perhaps
621 // we need to be more lazy about mutual possible views, even on an
622 // SVal? This may be necessary for bit-level reasoning as well.
623 return UnknownVal();
624 }
625
626 // We get a symbolic function pointer for a dereference of a function
627 // pointer, but it is of function type. Example:
628
629 // struct FPRec {
630 // void (*my_func)(int * x);
631 // };
632 //
633 // int bar(int x);
634 //
635 // int f1_a(struct FPRec* foo) {
636 // int x;
637 // (*foo->my_func)(&x);
638 // return bar(x)+1; // no-warning
639 // }
640
641 assert(Loc::isLocType(originalTy) || originalTy->isFunctionType() ||((Loc::isLocType(originalTy) || originalTy->isFunctionType
() || originalTy->isBlockPointerType() || castTy->isReferenceType
()) ? static_cast<void> (0) : __assert_fail ("Loc::isLocType(originalTy) || originalTy->isFunctionType() || originalTy->isBlockPointerType() || castTy->isReferenceType()"
, "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 642, __PRETTY_FUNCTION__))
642 originalTy->isBlockPointerType() || castTy->isReferenceType())((Loc::isLocType(originalTy) || originalTy->isFunctionType
() || originalTy->isBlockPointerType() || castTy->isReferenceType
()) ? static_cast<void> (0) : __assert_fail ("Loc::isLocType(originalTy) || originalTy->isFunctionType() || originalTy->isBlockPointerType() || castTy->isReferenceType()"
, "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp"
, 642, __PRETTY_FUNCTION__))
;
643
644 StoreManager &storeMgr = StateMgr.getStoreManager();
645
646 // Delegate to store manager to get the result of casting a region to a
647 // different type. If the MemRegion* returned is NULL, this expression
648 // Evaluates to UnknownVal.
649 R = storeMgr.castRegion(R, castTy);
650 return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
651 }
652
653 return dispatchCast(val, castTy);
654}

/build/llvm-toolchain-snapshot-9~svn362543/include/llvm/ADT/IntrusiveRefCntPtr.h

1//==- llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer --*- C++ -*-==//
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 the RefCountedBase, ThreadSafeRefCountedBase, and
10// IntrusiveRefCntPtr classes.
11//
12// IntrusiveRefCntPtr is a smart pointer to an object which maintains a
13// reference count. (ThreadSafe)RefCountedBase is a mixin class that adds a
14// refcount member variable and methods for updating the refcount. An object
15// that inherits from (ThreadSafe)RefCountedBase deletes itself when its
16// refcount hits zero.
17//
18// For example:
19//
20// class MyClass : public RefCountedBase<MyClass> {};
21//
22// void foo() {
23// // Constructing an IntrusiveRefCntPtr increases the pointee's refcount by
24// // 1 (from 0 in this case).
25// IntrusiveRefCntPtr<MyClass> Ptr1(new MyClass());
26//
27// // Copying an IntrusiveRefCntPtr increases the pointee's refcount by 1.
28// IntrusiveRefCntPtr<MyClass> Ptr2(Ptr1);
29//
30// // Constructing an IntrusiveRefCntPtr has no effect on the object's
31// // refcount. After a move, the moved-from pointer is null.
32// IntrusiveRefCntPtr<MyClass> Ptr3(std::move(Ptr1));
33// assert(Ptr1 == nullptr);
34//
35// // Clearing an IntrusiveRefCntPtr decreases the pointee's refcount by 1.
36// Ptr2.reset();
37//
38// // The object deletes itself when we return from the function, because
39// // Ptr3's destructor decrements its refcount to 0.
40// }
41//
42// You can use IntrusiveRefCntPtr with isa<T>(), dyn_cast<T>(), etc.:
43//
44// IntrusiveRefCntPtr<MyClass> Ptr(new MyClass());
45// OtherClass *Other = dyn_cast<OtherClass>(Ptr); // Ptr.get() not required
46//
47// IntrusiveRefCntPtr works with any class that
48//
49// - inherits from (ThreadSafe)RefCountedBase,
50// - has Retain() and Release() methods, or
51// - specializes IntrusiveRefCntPtrInfo.
52//
53//===----------------------------------------------------------------------===//
54
55#ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H
56#define LLVM_ADT_INTRUSIVEREFCNTPTR_H
57
58#include <atomic>
59#include <cassert>
60#include <cstddef>
61
62namespace llvm {
63
64/// A CRTP mixin class that adds reference counting to a type.
65///
66/// The lifetime of an object which inherits from RefCountedBase is managed by
67/// calls to Release() and Retain(), which increment and decrement the object's
68/// refcount, respectively. When a Release() call decrements the refcount to 0,
69/// the object deletes itself.
70template <class Derived> class RefCountedBase {
71 mutable unsigned RefCount = 0;
72
73public:
74 RefCountedBase() = default;
75 RefCountedBase(const RefCountedBase &) {}
76
77 void Retain() const { ++RefCount; }
78
79 void Release() const {
80 assert(RefCount > 0 && "Reference count is already zero.")((RefCount > 0 && "Reference count is already zero."
) ? static_cast<void> (0) : __assert_fail ("RefCount > 0 && \"Reference count is already zero.\""
, "/build/llvm-toolchain-snapshot-9~svn362543/include/llvm/ADT/IntrusiveRefCntPtr.h"
, 80, __PRETTY_FUNCTION__))
;
81 if (--RefCount == 0)
82 delete static_cast<const Derived *>(this);
83 }
84};
85
86/// A thread-safe version of \c RefCountedBase.
87template <class Derived> class ThreadSafeRefCountedBase {
88 mutable std::atomic<int> RefCount;
89
90protected:
91 ThreadSafeRefCountedBase() : RefCount(0) {}
92
93public:
94 void Retain() const { RefCount.fetch_add(1, std::memory_order_relaxed); }
95
96 void Release() const {
97 int NewRefCount = RefCount.fetch_sub(1, std::memory_order_acq_rel) - 1;
98 assert(NewRefCount >= 0 && "Reference count was already zero.")((NewRefCount >= 0 && "Reference count was already zero."
) ? static_cast<void> (0) : __assert_fail ("NewRefCount >= 0 && \"Reference count was already zero.\""
, "/build/llvm-toolchain-snapshot-9~svn362543/include/llvm/ADT/IntrusiveRefCntPtr.h"
, 98, __PRETTY_FUNCTION__))
;
99 if (NewRefCount == 0)
100 delete static_cast<const Derived *>(this);
101 }
102};
103
104/// Class you can specialize to provide custom retain/release functionality for
105/// a type.
106///
107/// Usually specializing this class is not necessary, as IntrusiveRefCntPtr
108/// works with any type which defines Retain() and Release() functions -- you
109/// can define those functions yourself if RefCountedBase doesn't work for you.
110///
111/// One case when you might want to specialize this type is if you have
112/// - Foo.h defines type Foo and includes Bar.h, and
113/// - Bar.h uses IntrusiveRefCntPtr<Foo> in inline functions.
114///
115/// Because Foo.h includes Bar.h, Bar.h can't include Foo.h in order to pull in
116/// the declaration of Foo. Without the declaration of Foo, normally Bar.h
117/// wouldn't be able to use IntrusiveRefCntPtr<Foo>, which wants to call
118/// T::Retain and T::Release.
119///
120/// To resolve this, Bar.h could include a third header, FooFwd.h, which
121/// forward-declares Foo and specializes IntrusiveRefCntPtrInfo<Foo>. Then
122/// Bar.h could use IntrusiveRefCntPtr<Foo>, although it still couldn't call any
123/// functions on Foo itself, because Foo would be an incomplete type.
124template <typename T> struct IntrusiveRefCntPtrInfo {
125 static void retain(T *obj) { obj->Retain(); }
126 static void release(T *obj) { obj->Release(); }
127};
128
129/// A smart pointer to a reference-counted object that inherits from
130/// RefCountedBase or ThreadSafeRefCountedBase.
131///
132/// This class increments its pointee's reference count when it is created, and
133/// decrements its refcount when it's destroyed (or is changed to point to a
134/// different object).
135template <typename T> class IntrusiveRefCntPtr {
136 T *Obj = nullptr;
137
138public:
139 using element_type = T;
140
141 explicit IntrusiveRefCntPtr() = default;
142 IntrusiveRefCntPtr(T *obj) : Obj(obj) { retain(); }
143 IntrusiveRefCntPtr(const IntrusiveRefCntPtr &S) : Obj(S.Obj) { retain(); }
144 IntrusiveRefCntPtr(IntrusiveRefCntPtr &&S) : Obj(S.Obj) { S.Obj = nullptr; }
145
146 template <class X>
147 IntrusiveRefCntPtr(IntrusiveRefCntPtr<X> &&S) : Obj(S.get()) {
148 S.Obj = nullptr;
149 }
150
151 template <class X>
152 IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X> &S) : Obj(S.get()) {
153 retain();
154 }
155
156 ~IntrusiveRefCntPtr() { release(); }
157
158 IntrusiveRefCntPtr &operator=(IntrusiveRefCntPtr S) {
159 swap(S);
160 return *this;
161 }
162
163 T &operator*() const { return *Obj; }
164 T *operator->() const { return Obj; }
2
Returning pointer
165 T *get() const { return Obj; }
166 explicit operator bool() const { return Obj; }
167
168 void swap(IntrusiveRefCntPtr &other) {
169 T *tmp = other.Obj;
170 other.Obj = Obj;
171 Obj = tmp;
172 }
173
174 void reset() {
175 release();
176 Obj = nullptr;
177 }
178
179 void resetWithoutRelease() { Obj = nullptr; }
180
181private:
182 void retain() {
183 if (Obj)
184 IntrusiveRefCntPtrInfo<T>::retain(Obj);
185 }
186
187 void release() {
188 if (Obj)
189 IntrusiveRefCntPtrInfo<T>::release(Obj);
190 }
191
192 template <typename X> friend class IntrusiveRefCntPtr;
193};
194
195template <class T, class U>
196inline bool operator==(const IntrusiveRefCntPtr<T> &A,
197 const IntrusiveRefCntPtr<U> &B) {
198 return A.get() == B.get();
199}
200
201template <class T, class U>
202inline bool operator!=(const IntrusiveRefCntPtr<T> &A,
203 const IntrusiveRefCntPtr<U> &B) {
204 return A.get() != B.get();
205}
206
207template <class T, class U>
208inline bool operator==(const IntrusiveRefCntPtr<T> &A, U *B) {
209 return A.get() == B;
210}
211
212template <class T, class U>
213inline bool operator!=(const IntrusiveRefCntPtr<T> &A, U *B) {
214 return A.get() != B;
215}
216
217template <class T, class U>
218inline bool operator==(T *A, const IntrusiveRefCntPtr<U> &B) {
219 return A == B.get();
220}
221
222template <class T, class U>
223inline bool operator!=(T *A, const IntrusiveRefCntPtr<U> &B) {
224 return A != B.get();
225}
226
227template <class T>
228bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
229 return !B;
230}
231
232template <class T>
233bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
234 return B == A;
235}
236
237template <class T>
238bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
239 return !(A == B);
240}
241
242template <class T>
243bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
244 return !(A == B);
245}
246
247// Make IntrusiveRefCntPtr work with dyn_cast, isa, and the other idioms from
248// Casting.h.
249template <typename From> struct simplify_type;
250
251template <class T> struct simplify_type<IntrusiveRefCntPtr<T>> {
252 using SimpleType = T *;
253
254 static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T> &Val) {
255 return Val.get();
256 }
257};
258
259template <class T> struct simplify_type<const IntrusiveRefCntPtr<T>> {
260 using SimpleType = /*const*/ T *;
261
262 static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T> &Val) {
263 return Val.get();
264 }
265};
266
267} // end namespace llvm
268
269#endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H