Bug Summary

File:build/source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
Warning:line 315, column 33
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ExprEngineCXX.cpp -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 -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm -resource-dir /usr/lib/llvm-16/lib/clang/16.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/clang/lib/StaticAnalyzer/Core -I /build/source/clang/lib/StaticAnalyzer/Core -I /build/source/clang/include -I tools/clang/include -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-16/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm=build-llvm -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm=build-llvm -fcoverage-prefix-map=/build/source/= -source-date-epoch 1668078801 -O3 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm -fdebug-prefix-map=/build/source/build-llvm=build-llvm -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-11-10-135928-647445-1 -x c++ /build/source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

/build/source/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

1//===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- 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 C++ expression evaluation engine.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/AST/DeclCXX.h"
14#include "clang/AST/ParentMap.h"
15#include "clang/AST/StmtCXX.h"
16#include "clang/Analysis/ConstructionContext.h"
17#include "clang/Basic/PrettyStackTrace.h"
18#include "clang/StaticAnalyzer/Core/CheckerManager.h"
19#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
20#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
21#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
22#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
23
24using namespace clang;
25using namespace ento;
26
27void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
28 ExplodedNode *Pred,
29 ExplodedNodeSet &Dst) {
30 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
31 const Expr *tempExpr = ME->getSubExpr()->IgnoreParens();
32 ProgramStateRef state = Pred->getState();
33 const LocationContext *LCtx = Pred->getLocationContext();
34
35 state = createTemporaryRegionIfNeeded(state, LCtx, tempExpr, ME);
36 Bldr.generateNode(ME, Pred, state);
37}
38
39// FIXME: This is the sort of code that should eventually live in a Core
40// checker rather than as a special case in ExprEngine.
41void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
42 const CallEvent &Call) {
43 SVal ThisVal;
44 bool AlwaysReturnsLValue;
45 const CXXRecordDecl *ThisRD = nullptr;
46 if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
47 assert(Ctor->getDecl()->isTrivial())(static_cast <bool> (Ctor->getDecl()->isTrivial()
) ? void (0) : __assert_fail ("Ctor->getDecl()->isTrivial()"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 47, __extension__
__PRETTY_FUNCTION__))
;
48 assert(Ctor->getDecl()->isCopyOrMoveConstructor())(static_cast <bool> (Ctor->getDecl()->isCopyOrMoveConstructor
()) ? void (0) : __assert_fail ("Ctor->getDecl()->isCopyOrMoveConstructor()"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 48, __extension__
__PRETTY_FUNCTION__))
;
49 ThisVal = Ctor->getCXXThisVal();
50 ThisRD = Ctor->getDecl()->getParent();
51 AlwaysReturnsLValue = false;
52 } else {
53 assert(cast<CXXMethodDecl>(Call.getDecl())->isTrivial())(static_cast <bool> (cast<CXXMethodDecl>(Call.getDecl
())->isTrivial()) ? void (0) : __assert_fail ("cast<CXXMethodDecl>(Call.getDecl())->isTrivial()"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 53, __extension__
__PRETTY_FUNCTION__))
;
54 assert(cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() ==(static_cast <bool> (cast<CXXMethodDecl>(Call.getDecl
())->getOverloadedOperator() == OO_Equal) ? void (0) : __assert_fail
("cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() == OO_Equal"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 55, __extension__
__PRETTY_FUNCTION__))
55 OO_Equal)(static_cast <bool> (cast<CXXMethodDecl>(Call.getDecl
())->getOverloadedOperator() == OO_Equal) ? void (0) : __assert_fail
("cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() == OO_Equal"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 55, __extension__
__PRETTY_FUNCTION__))
;
56 ThisVal = cast<CXXInstanceCall>(Call).getCXXThisVal();
57 ThisRD = cast<CXXMethodDecl>(Call.getDecl())->getParent();
58 AlwaysReturnsLValue = true;
59 }
60
61 assert(ThisRD)(static_cast <bool> (ThisRD) ? void (0) : __assert_fail
("ThisRD", "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp"
, 61, __extension__ __PRETTY_FUNCTION__))
;
62 if (ThisRD->isEmpty()) {
63 // Do nothing for empty classes. Otherwise it'd retrieve an UnknownVal
64 // and bind it and RegionStore would think that the actual value
65 // in this region at this offset is unknown.
66 return;
67 }
68
69 const LocationContext *LCtx = Pred->getLocationContext();
70
71 ExplodedNodeSet Dst;
72 Bldr.takeNodes(Pred);
73
74 SVal V = Call.getArgSVal(0);
75
76 // If the value being copied is not unknown, load from its location to get
77 // an aggregate rvalue.
78 if (Optional<Loc> L = V.getAs<Loc>())
79 V = Pred->getState()->getSVal(*L);
80 else
81 assert(V.isUnknownOrUndef())(static_cast <bool> (V.isUnknownOrUndef()) ? void (0) :
__assert_fail ("V.isUnknownOrUndef()", "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp"
, 81, __extension__ __PRETTY_FUNCTION__))
;
82
83 const Expr *CallExpr = Call.getOriginExpr();
84 evalBind(Dst, CallExpr, Pred, ThisVal, V, true);
85
86 PostStmt PS(CallExpr, LCtx);
87 for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end();
88 I != E; ++I) {
89 ProgramStateRef State = (*I)->getState();
90 if (AlwaysReturnsLValue)
91 State = State->BindExpr(CallExpr, LCtx, ThisVal);
92 else
93 State = bindReturnValue(Call, LCtx, State);
94 Bldr.generateNode(PS, State, *I);
95 }
96}
97
98SVal ExprEngine::makeElementRegion(ProgramStateRef State, SVal LValue,
99 QualType &Ty, bool &IsArray, unsigned Idx) {
100 SValBuilder &SVB = State->getStateManager().getSValBuilder();
101 ASTContext &Ctx = SVB.getContext();
102
103 if (const ArrayType *AT = Ctx.getAsArrayType(Ty)) {
104 while (AT) {
105 Ty = AT->getElementType();
106 AT = dyn_cast<ArrayType>(AT->getElementType());
107 }
108 LValue = State->getLValue(Ty, SVB.makeArrayIndex(Idx), LValue);
109 IsArray = true;
110 }
111
112 return LValue;
113}
114
115// In case when the prvalue is returned from the function (kind is one of
116// SimpleReturnedValueKind, CXX17ElidedCopyReturnedValueKind), then
117// it's materialization happens in context of the caller.
118// We pass BldrCtx explicitly, as currBldrCtx always refers to callee's context.
119SVal ExprEngine::computeObjectUnderConstruction(
120 const Expr *E, ProgramStateRef State, const NodeBuilderContext *BldrCtx,
121 const LocationContext *LCtx, const ConstructionContext *CC,
122 EvalCallOptions &CallOpts, unsigned Idx) {
123
124 SValBuilder &SVB = getSValBuilder();
125 MemRegionManager &MRMgr = SVB.getRegionManager();
126 ASTContext &ACtx = SVB.getContext();
127
128 // Compute the target region by exploring the construction context.
129 if (CC
19.1
'CC' is non-null
19.1
'CC' is non-null
) {
20
Taking true branch
27
Assuming 'CC' is non-null
28
Taking true branch
130 switch (CC->getKind()) {
21
Control jumps to 'case ElidedTemporaryObjectKind:' at line 249
29
Control jumps to 'case LambdaCaptureKind:' at line 304
131 case ConstructionContext::CXX17ElidedCopyVariableKind:
132 case ConstructionContext::SimpleVariableKind: {
133 const auto *DSCC = cast<VariableConstructionContext>(CC);
134 const auto *DS = DSCC->getDeclStmt();
135 const auto *Var = cast<VarDecl>(DS->getSingleDecl());
136 QualType Ty = Var->getType();
137 return makeElementRegion(State, State->getLValue(Var, LCtx), Ty,
138 CallOpts.IsArrayCtorOrDtor, Idx);
139 }
140 case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind:
141 case ConstructionContext::SimpleConstructorInitializerKind: {
142 const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC);
143 const auto *Init = ICC->getCXXCtorInitializer();
144 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
145 Loc ThisPtr = SVB.getCXXThis(CurCtor, LCtx->getStackFrame());
146 SVal ThisVal = State->getSVal(ThisPtr);
147 if (Init->isBaseInitializer()) {
148 const auto *ThisReg = cast<SubRegion>(ThisVal.getAsRegion());
149 const CXXRecordDecl *BaseClass =
150 Init->getBaseClass()->getAsCXXRecordDecl();
151 const auto *BaseReg =
152 MRMgr.getCXXBaseObjectRegion(BaseClass, ThisReg,
153 Init->isBaseVirtual());
154 return SVB.makeLoc(BaseReg);
155 }
156 if (Init->isDelegatingInitializer())
157 return ThisVal;
158
159 const ValueDecl *Field;
160 SVal FieldVal;
161 if (Init->isIndirectMemberInitializer()) {
162 Field = Init->getIndirectMember();
163 FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal);
164 } else {
165 Field = Init->getMember();
166 FieldVal = State->getLValue(Init->getMember(), ThisVal);
167 }
168
169 QualType Ty = Field->getType();
170 return makeElementRegion(State, FieldVal, Ty, CallOpts.IsArrayCtorOrDtor,
171 Idx);
172 }
173 case ConstructionContext::NewAllocatedObjectKind: {
174 if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
175 const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
176 const auto *NE = NECC->getCXXNewExpr();
177 SVal V = *getObjectUnderConstruction(State, NE, LCtx);
178 if (const SubRegion *MR =
179 dyn_cast_or_null<SubRegion>(V.getAsRegion())) {
180 if (NE->isArray()) {
181 CallOpts.IsArrayCtorOrDtor = true;
182
183 auto Ty = NE->getType()->getPointeeType();
184 while (const auto *AT = getContext().getAsArrayType(Ty))
185 Ty = AT->getElementType();
186
187 auto R = MRMgr.getElementRegion(Ty, svalBuilder.makeArrayIndex(Idx),
188 MR, SVB.getContext());
189
190 return loc::MemRegionVal(R);
191 }
192 return V;
193 }
194 // TODO: Detect when the allocator returns a null pointer.
195 // Constructor shall not be called in this case.
196 }
197 break;
198 }
199 case ConstructionContext::SimpleReturnedValueKind:
200 case ConstructionContext::CXX17ElidedCopyReturnedValueKind: {
201 // The temporary is to be managed by the parent stack frame.
202 // So build it in the parent stack frame if we're not in the
203 // top frame of the analysis.
204 const StackFrameContext *SFC = LCtx->getStackFrame();
205 if (const LocationContext *CallerLCtx = SFC->getParent()) {
206 auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()]
207 .getAs<CFGCXXRecordTypedCall>();
208 if (!RTC) {
209 // We were unable to find the correct construction context for the
210 // call in the parent stack frame. This is equivalent to not being
211 // able to find construction context at all.
212 break;
213 }
214 if (isa<BlockInvocationContext>(CallerLCtx)) {
215 // Unwrap block invocation contexts. They're mostly part of
216 // the current stack frame.
217 CallerLCtx = CallerLCtx->getParent();
218 assert(!isa<BlockInvocationContext>(CallerLCtx))(static_cast <bool> (!isa<BlockInvocationContext>
(CallerLCtx)) ? void (0) : __assert_fail ("!isa<BlockInvocationContext>(CallerLCtx)"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 218, __extension__
__PRETTY_FUNCTION__))
;
219 }
220
221 NodeBuilderContext CallerBldrCtx(getCoreEngine(),
222 SFC->getCallSiteBlock(), CallerLCtx);
223 return computeObjectUnderConstruction(
224 cast<Expr>(SFC->getCallSite()), State, &CallerBldrCtx, CallerLCtx,
225 RTC->getConstructionContext(), CallOpts);
226 } else {
227 // We are on the top frame of the analysis. We do not know where is the
228 // object returned to. Conjure a symbolic region for the return value.
229 // TODO: We probably need a new MemRegion kind to represent the storage
230 // of that SymbolicRegion, so that we cound produce a fancy symbol
231 // instead of an anonymous conjured symbol.
232 // TODO: Do we need to track the region to avoid having it dead
233 // too early? It does die too early, at least in C++17, but because
234 // putting anything into a SymbolicRegion causes an immediate escape,
235 // it doesn't cause any leak false positives.
236 const auto *RCC = cast<ReturnedValueConstructionContext>(CC);
237 // Make sure that this doesn't coincide with any other symbol
238 // conjured for the returned expression.
239 static const int TopLevelSymRegionTag = 0;
240 const Expr *RetE = RCC->getReturnStmt()->getRetValue();
241 assert(RetE && "Void returns should not have a construction context")(static_cast <bool> (RetE && "Void returns should not have a construction context"
) ? void (0) : __assert_fail ("RetE && \"Void returns should not have a construction context\""
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 241, __extension__
__PRETTY_FUNCTION__))
;
242 QualType ReturnTy = RetE->getType();
243 QualType RegionTy = ACtx.getPointerType(ReturnTy);
244 return SVB.conjureSymbolVal(&TopLevelSymRegionTag, RetE, SFC, RegionTy,
245 currBldrCtx->blockCount());
246 }
247 llvm_unreachable("Unhandled return value construction context!")::llvm::llvm_unreachable_internal("Unhandled return value construction context!"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 247)
;
248 }
249 case ConstructionContext::ElidedTemporaryObjectKind: {
250 assert(AMgr.getAnalyzerOptions().ShouldElideConstructors)(static_cast <bool> (AMgr.getAnalyzerOptions().ShouldElideConstructors
) ? void (0) : __assert_fail ("AMgr.getAnalyzerOptions().ShouldElideConstructors"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 250, __extension__
__PRETTY_FUNCTION__))
;
22
Assuming field 'ShouldElideConstructors' is true
23
'?' condition is true
251 const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
24
'CC' is a 'CastReturnType'
252
253 // Support pre-C++17 copy elision. We'll have the elidable copy
254 // constructor in the AST and in the CFG, but we'll skip it
255 // and construct directly into the final object. This call
256 // also sets the CallOpts flags for us.
257 // If the elided copy/move constructor is not supported, there's still
258 // benefit in trying to model the non-elided constructor.
259 // Stash our state before trying to elide, as it'll get overwritten.
260 ProgramStateRef PreElideState = State;
261 EvalCallOptions PreElideCallOpts = CallOpts;
262
263 SVal V = computeObjectUnderConstruction(
26
Calling 'ExprEngine::computeObjectUnderConstruction'
264 TCC->getConstructorAfterElision(), State, BldrCtx, LCtx,
25
Passing value via 1st parameter 'E'
265 TCC->getConstructionContextAfterElision(), CallOpts);
266
267 // FIXME: This definition of "copy elision has not failed" is unreliable.
268 // It doesn't indicate that the constructor will actually be inlined
269 // later; this is still up to evalCall() to decide.
270 if (!CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion)
271 return V;
272
273 // Copy elision failed. Revert the changes and proceed as if we have
274 // a simple temporary.
275 CallOpts = PreElideCallOpts;
276 CallOpts.IsElidableCtorThatHasNotBeenElided = true;
277 [[fallthrough]];
278 }
279 case ConstructionContext::SimpleTemporaryObjectKind: {
280 const auto *TCC = cast<TemporaryObjectConstructionContext>(CC);
281 const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr();
282
283 CallOpts.IsTemporaryCtorOrDtor = true;
284 if (MTE) {
285 if (const ValueDecl *VD = MTE->getExtendingDecl()) {
286 assert(MTE->getStorageDuration() != SD_FullExpression)(static_cast <bool> (MTE->getStorageDuration() != SD_FullExpression
) ? void (0) : __assert_fail ("MTE->getStorageDuration() != SD_FullExpression"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 286, __extension__
__PRETTY_FUNCTION__))
;
287 if (!VD->getType()->isReferenceType()) {
288 // We're lifetime-extended by a surrounding aggregate.
289 // Automatic destructors aren't quite working in this case
290 // on the CFG side. We should warn the caller about that.
291 // FIXME: Is there a better way to retrieve this information from
292 // the MaterializeTemporaryExpr?
293 CallOpts.IsTemporaryLifetimeExtendedViaAggregate = true;
294 }
295 }
296
297 if (MTE->getStorageDuration() == SD_Static ||
298 MTE->getStorageDuration() == SD_Thread)
299 return loc::MemRegionVal(MRMgr.getCXXStaticTempObjectRegion(E));
300 }
301
302 return loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx));
303 }
304 case ConstructionContext::LambdaCaptureKind: {
305 CallOpts.IsTemporaryCtorOrDtor = true;
306
307 const auto *LCC = cast<LambdaCaptureConstructionContext>(CC);
30
'CC' is a 'CastReturnType'
308
309 SVal Base = loc::MemRegionVal(
310 MRMgr.getCXXTempObjectRegion(LCC->getInitializer(), LCtx));
311
312 const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E);
31
Assuming null pointer is passed into cast
313 if (getIndexOfElementToConstruct(State, CE, LCtx)) {
32
Assuming the condition is true
33
Taking true branch
314 CallOpts.IsArrayCtorOrDtor = true;
315 Base = State->getLValue(E->getType(), svalBuilder.makeArrayIndex(Idx),
34
Called C++ object pointer is null
316 Base);
317 }
318
319 return Base;
320 }
321 case ConstructionContext::ArgumentKind: {
322 // Arguments are technically temporaries.
323 CallOpts.IsTemporaryCtorOrDtor = true;
324
325 const auto *ACC = cast<ArgumentConstructionContext>(CC);
326 const Expr *E = ACC->getCallLikeExpr();
327 unsigned Idx = ACC->getIndex();
328
329 CallEventManager &CEMgr = getStateManager().getCallEventManager();
330 auto getArgLoc = [&](CallEventRef<> Caller) -> Optional<SVal> {
331 const LocationContext *FutureSFC =
332 Caller->getCalleeStackFrame(BldrCtx->blockCount());
333 // Return early if we are unable to reliably foresee
334 // the future stack frame.
335 if (!FutureSFC)
336 return None;
337
338 // This should be equivalent to Caller->getDecl() for now, but
339 // FutureSFC->getDecl() is likely to support better stuff (like
340 // virtual functions) earlier.
341 const Decl *CalleeD = FutureSFC->getDecl();
342
343 // FIXME: Support for variadic arguments is not implemented here yet.
344 if (CallEvent::isVariadic(CalleeD))
345 return None;
346
347 // Operator arguments do not correspond to operator parameters
348 // because this-argument is implemented as a normal argument in
349 // operator call expressions but not in operator declarations.
350 const TypedValueRegion *TVR = Caller->getParameterLocation(
351 *Caller->getAdjustedParameterIndex(Idx), BldrCtx->blockCount());
352 if (!TVR)
353 return None;
354
355 return loc::MemRegionVal(TVR);
356 };
357
358 if (const auto *CE = dyn_cast<CallExpr>(E)) {
359 CallEventRef<> Caller = CEMgr.getSimpleCall(CE, State, LCtx);
360 if (Optional<SVal> V = getArgLoc(Caller))
361 return *V;
362 else
363 break;
364 } else if (const auto *CCE = dyn_cast<CXXConstructExpr>(E)) {
365 // Don't bother figuring out the target region for the future
366 // constructor because we won't need it.
367 CallEventRef<> Caller =
368 CEMgr.getCXXConstructorCall(CCE, /*Target=*/nullptr, State, LCtx);
369 if (Optional<SVal> V = getArgLoc(Caller))
370 return *V;
371 else
372 break;
373 } else if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
374 CallEventRef<> Caller = CEMgr.getObjCMethodCall(ME, State, LCtx);
375 if (Optional<SVal> V = getArgLoc(Caller))
376 return *V;
377 else
378 break;
379 }
380 }
381 } // switch (CC->getKind())
382 }
383
384 // If we couldn't find an existing region to construct into, assume we're
385 // constructing a temporary. Notify the caller of our failure.
386 CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;
387 return loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx));
388}
389
390ProgramStateRef ExprEngine::updateObjectsUnderConstruction(
391 SVal V, const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
392 const ConstructionContext *CC, const EvalCallOptions &CallOpts) {
393 if (CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion) {
394 // Sounds like we failed to find the target region and therefore
395 // copy elision failed. There's nothing we can do about it here.
396 return State;
397 }
398
399 // See if we're constructing an existing region by looking at the
400 // current construction context.
401 assert(CC && "Computed target region without construction context?")(static_cast <bool> (CC && "Computed target region without construction context?"
) ? void (0) : __assert_fail ("CC && \"Computed target region without construction context?\""
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 401, __extension__
__PRETTY_FUNCTION__))
;
402 switch (CC->getKind()) {
403 case ConstructionContext::CXX17ElidedCopyVariableKind:
404 case ConstructionContext::SimpleVariableKind: {
405 const auto *DSCC = cast<VariableConstructionContext>(CC);
406 return addObjectUnderConstruction(State, DSCC->getDeclStmt(), LCtx, V);
407 }
408 case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind:
409 case ConstructionContext::SimpleConstructorInitializerKind: {
410 const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC);
411 const auto *Init = ICC->getCXXCtorInitializer();
412 // Base and delegating initializers handled above
413 assert(Init->isAnyMemberInitializer() &&(static_cast <bool> (Init->isAnyMemberInitializer() &&
"Base and delegating initializers should have been handled by"
"computeObjectUnderConstruction()") ? void (0) : __assert_fail
("Init->isAnyMemberInitializer() && \"Base and delegating initializers should have been handled by\" \"computeObjectUnderConstruction()\""
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 415, __extension__
__PRETTY_FUNCTION__))
414 "Base and delegating initializers should have been handled by"(static_cast <bool> (Init->isAnyMemberInitializer() &&
"Base and delegating initializers should have been handled by"
"computeObjectUnderConstruction()") ? void (0) : __assert_fail
("Init->isAnyMemberInitializer() && \"Base and delegating initializers should have been handled by\" \"computeObjectUnderConstruction()\""
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 415, __extension__
__PRETTY_FUNCTION__))
415 "computeObjectUnderConstruction()")(static_cast <bool> (Init->isAnyMemberInitializer() &&
"Base and delegating initializers should have been handled by"
"computeObjectUnderConstruction()") ? void (0) : __assert_fail
("Init->isAnyMemberInitializer() && \"Base and delegating initializers should have been handled by\" \"computeObjectUnderConstruction()\""
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 415, __extension__
__PRETTY_FUNCTION__))
;
416 return addObjectUnderConstruction(State, Init, LCtx, V);
417 }
418 case ConstructionContext::NewAllocatedObjectKind: {
419 return State;
420 }
421 case ConstructionContext::SimpleReturnedValueKind:
422 case ConstructionContext::CXX17ElidedCopyReturnedValueKind: {
423 const StackFrameContext *SFC = LCtx->getStackFrame();
424 const LocationContext *CallerLCtx = SFC->getParent();
425 if (!CallerLCtx) {
426 // No extra work is necessary in top frame.
427 return State;
428 }
429
430 auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()]
431 .getAs<CFGCXXRecordTypedCall>();
432 assert(RTC && "Could not have had a target region without it")(static_cast <bool> (RTC && "Could not have had a target region without it"
) ? void (0) : __assert_fail ("RTC && \"Could not have had a target region without it\""
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 432, __extension__
__PRETTY_FUNCTION__))
;
433 if (isa<BlockInvocationContext>(CallerLCtx)) {
434 // Unwrap block invocation contexts. They're mostly part of
435 // the current stack frame.
436 CallerLCtx = CallerLCtx->getParent();
437 assert(!isa<BlockInvocationContext>(CallerLCtx))(static_cast <bool> (!isa<BlockInvocationContext>
(CallerLCtx)) ? void (0) : __assert_fail ("!isa<BlockInvocationContext>(CallerLCtx)"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 437, __extension__
__PRETTY_FUNCTION__))
;
438 }
439
440 return updateObjectsUnderConstruction(V,
441 cast<Expr>(SFC->getCallSite()), State, CallerLCtx,
442 RTC->getConstructionContext(), CallOpts);
443 }
444 case ConstructionContext::ElidedTemporaryObjectKind: {
445 assert(AMgr.getAnalyzerOptions().ShouldElideConstructors)(static_cast <bool> (AMgr.getAnalyzerOptions().ShouldElideConstructors
) ? void (0) : __assert_fail ("AMgr.getAnalyzerOptions().ShouldElideConstructors"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 445, __extension__
__PRETTY_FUNCTION__))
;
446 if (!CallOpts.IsElidableCtorThatHasNotBeenElided) {
447 const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
448 State = updateObjectsUnderConstruction(
449 V, TCC->getConstructorAfterElision(), State, LCtx,
450 TCC->getConstructionContextAfterElision(), CallOpts);
451
452 // Remember that we've elided the constructor.
453 State = addObjectUnderConstruction(
454 State, TCC->getConstructorAfterElision(), LCtx, V);
455
456 // Remember that we've elided the destructor.
457 if (const auto *BTE = TCC->getCXXBindTemporaryExpr())
458 State = elideDestructor(State, BTE, LCtx);
459
460 // Instead of materialization, shamelessly return
461 // the final object destination.
462 if (const auto *MTE = TCC->getMaterializedTemporaryExpr())
463 State = addObjectUnderConstruction(State, MTE, LCtx, V);
464
465 return State;
466 }
467 // If we decided not to elide the constructor, proceed as if
468 // it's a simple temporary.
469 [[fallthrough]];
470 }
471 case ConstructionContext::SimpleTemporaryObjectKind: {
472 const auto *TCC = cast<TemporaryObjectConstructionContext>(CC);
473 if (const auto *BTE = TCC->getCXXBindTemporaryExpr())
474 State = addObjectUnderConstruction(State, BTE, LCtx, V);
475
476 if (const auto *MTE = TCC->getMaterializedTemporaryExpr())
477 State = addObjectUnderConstruction(State, MTE, LCtx, V);
478
479 return State;
480 }
481 case ConstructionContext::LambdaCaptureKind: {
482 const auto *LCC = cast<LambdaCaptureConstructionContext>(CC);
483
484 // If we capture and array, we want to store the super region, not a
485 // sub-region.
486 if (const auto *EL = dyn_cast_or_null<ElementRegion>(V.getAsRegion()))
487 V = loc::MemRegionVal(EL->getSuperRegion());
488
489 return addObjectUnderConstruction(
490 State, {LCC->getLambdaExpr(), LCC->getIndex()}, LCtx, V);
491 }
492 case ConstructionContext::ArgumentKind: {
493 const auto *ACC = cast<ArgumentConstructionContext>(CC);
494 if (const auto *BTE = ACC->getCXXBindTemporaryExpr())
495 State = addObjectUnderConstruction(State, BTE, LCtx, V);
496
497 return addObjectUnderConstruction(
498 State, {ACC->getCallLikeExpr(), ACC->getIndex()}, LCtx, V);
499 }
500 }
501 llvm_unreachable("Unhandled construction context!")::llvm::llvm_unreachable_internal("Unhandled construction context!"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 501)
;
502}
503
504static ProgramStateRef
505bindRequiredArrayElementToEnvironment(ProgramStateRef State,
506 const ArrayInitLoopExpr *AILE,
507 const LocationContext *LCtx, SVal Idx) {
508 // The ctor in this case is guaranteed to be a copy ctor, otherwise we hit a
509 // compile time error.
510 //
511 // -ArrayInitLoopExpr <-- we're here
512 // |-OpaqueValueExpr
513 // | `-DeclRefExpr <-- match this
514 // `-CXXConstructExpr
515 // `-ImplicitCastExpr
516 // `-ArraySubscriptExpr
517 // |-ImplicitCastExpr
518 // | `-OpaqueValueExpr
519 // | `-DeclRefExpr
520 // `-ArrayInitIndexExpr
521 //
522 // The resulting expression might look like the one below in an implicit
523 // copy/move ctor.
524 //
525 // ArrayInitLoopExpr <-- we're here
526 // |-OpaqueValueExpr
527 // | `-MemberExpr <-- match this
528 // | (`-CXXStaticCastExpr) <-- move ctor only
529 // | `-DeclRefExpr
530 // `-CXXConstructExpr
531 // `-ArraySubscriptExpr
532 // |-ImplicitCastExpr
533 // | `-OpaqueValueExpr
534 // | `-MemberExpr
535 // | `-DeclRefExpr
536 // `-ArrayInitIndexExpr
537 //
538 // The resulting expression for a multidimensional array.
539 // ArrayInitLoopExpr <-- we're here
540 // |-OpaqueValueExpr
541 // | `-DeclRefExpr <-- match this
542 // `-ArrayInitLoopExpr
543 // |-OpaqueValueExpr
544 // | `-ArraySubscriptExpr
545 // | |-ImplicitCastExpr
546 // | | `-OpaqueValueExpr
547 // | | `-DeclRefExpr
548 // | `-ArrayInitIndexExpr
549 // `-CXXConstructExpr <-- extract this
550 // ` ...
551
552 const auto *OVESrc = AILE->getCommonExpr()->getSourceExpr();
553
554 // HACK: There is no way we can put the index of the array element into the
555 // CFG unless we unroll the loop, so we manually select and bind the required
556 // parameter to the environment.
557 const auto *CE =
558 cast<CXXConstructExpr>(extractElementInitializerFromNestedAILE(AILE));
559
560 SVal Base = UnknownVal();
561 if (const auto *ME = dyn_cast<MemberExpr>(OVESrc))
562 Base = State->getSVal(ME, LCtx);
563 else if (const auto *DRE = dyn_cast<DeclRefExpr>(OVESrc))
564 Base = State->getLValue(cast<VarDecl>(DRE->getDecl()), LCtx);
565 else
566 llvm_unreachable("ArrayInitLoopExpr contains unexpected source expression")::llvm::llvm_unreachable_internal("ArrayInitLoopExpr contains unexpected source expression"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 566)
;
567
568 SVal NthElem = State->getLValue(CE->getType(), Idx, Base);
569
570 return State->BindExpr(CE->getArg(0), LCtx, NthElem);
571}
572
573void ExprEngine::handleConstructor(const Expr *E,
574 ExplodedNode *Pred,
575 ExplodedNodeSet &destNodes) {
576 const auto *CE = dyn_cast<CXXConstructExpr>(E);
1
Assuming 'E' is a 'CastReturnType'
577 const auto *CIE = dyn_cast<CXXInheritedCtorInitExpr>(E);
2
Assuming 'E' is not a 'CastReturnType'
578 assert(CE || CIE)(static_cast <bool> (CE || CIE) ? void (0) : __assert_fail
("CE || CIE", "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp"
, 578, __extension__ __PRETTY_FUNCTION__))
;
3
'?' condition is true
579
580 const LocationContext *LCtx = Pred->getLocationContext();
581 ProgramStateRef State = Pred->getState();
582
583 SVal Target = UnknownVal();
584
585 if (CE
3.1
'CE' is non-null
3.1
'CE' is non-null
) {
4
Taking true branch
586 if (Optional<SVal> ElidedTarget =
5
Assuming the condition is false
6
Taking false branch
587 getObjectUnderConstruction(State, CE, LCtx)) {
588 // We've previously modeled an elidable constructor by pretending that it
589 // in fact constructs into the correct target. This constructor can
590 // therefore be skipped.
591 Target = *ElidedTarget;
592 StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx);
593 State = finishObjectConstruction(State, CE, LCtx);
594 if (auto L = Target.getAs<Loc>())
595 State = State->BindExpr(CE, LCtx, State->getSVal(*L, CE->getType()));
596 Bldr.generateNode(CE, Pred, State);
597 return;
598 }
599 }
600
601 EvalCallOptions CallOpts;
602 auto C = getCurrentCFGElement().getAs<CFGConstructor>();
603 assert(C || getCurrentCFGElement().getAs<CFGStmt>())(static_cast <bool> (C || getCurrentCFGElement().getAs<
CFGStmt>()) ? void (0) : __assert_fail ("C || getCurrentCFGElement().getAs<CFGStmt>()"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 603, __extension__
__PRETTY_FUNCTION__))
;
7
Assuming the condition is true
8
'?' condition is true
604 const ConstructionContext *CC = C ? C->getConstructionContext() : nullptr;
9
'?' condition is true
605
606 const CXXConstructExpr::ConstructionKind CK =
607 CE
9.1
'CE' is non-null
9.1
'CE' is non-null
? CE->getConstructionKind() : CIE->getConstructionKind();
10
'?' condition is true
608 switch (CK) {
11
Control jumps to 'case CK_Complete:' at line 609
609 case CXXConstructExpr::CK_Complete: {
610 // Inherited constructors are always base class constructors.
611 assert(CE && !CIE && "A complete constructor is inherited?!")(static_cast <bool> (CE && !CIE && "A complete constructor is inherited?!"
) ? void (0) : __assert_fail ("CE && !CIE && \"A complete constructor is inherited?!\""
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 611, __extension__
__PRETTY_FUNCTION__))
;
12
'?' condition is true
612
613 // If the ctor is part of an ArrayInitLoopExpr, we want to handle it
614 // differently.
615 auto *AILE = CC ? CC->getArrayInitLoop() : nullptr;
13
Assuming 'CC' is non-null
14
'?' condition is true
616
617 unsigned Idx = 0;
618 if (CE->getType()->isArrayType() || AILE) {
15
Assuming the condition is false
16
Taking false branch
619
620 auto isZeroSizeArray = [&] {
621 uint64_t Size = 1;
622
623 if (const auto *CAT = dyn_cast<ConstantArrayType>(CE->getType()))
624 Size = getContext().getConstantArrayElementCount(CAT);
625 else if (AILE)
626 Size = getContext().getArrayInitLoopExprElementCount(AILE);
627
628 return Size == 0;
629 };
630
631 // No element construction will happen in a 0 size array.
632 if (isZeroSizeArray()) {
633 StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx);
634 static SimpleProgramPointTag T{"ExprEngine",
635 "Skipping 0 size array construction"};
636 Bldr.generateNode(CE, Pred, State, &T);
637 return;
638 }
639
640 Idx = getIndexOfElementToConstruct(State, CE, LCtx).value_or(0u);
641 State = setIndexOfElementToConstruct(State, CE, LCtx, Idx + 1);
642 }
643
644 if (AILE
16.1
'AILE' is null
16.1
'AILE' is null
) {
17
Taking false branch
645 // Only set this once even though we loop through it multiple times.
646 if (!getPendingInitLoop(State, CE, LCtx))
647 State = setPendingInitLoop(
648 State, CE, LCtx,
649 getContext().getArrayInitLoopExprElementCount(AILE));
650
651 State = bindRequiredArrayElementToEnvironment(
652 State, AILE, LCtx, svalBuilder.makeArrayIndex(Idx));
653 }
654
655 // The target region is found from construction context.
656 std::tie(State, Target) = handleConstructionContext(
18
Calling 'ExprEngine::handleConstructionContext'
657 CE, State, currBldrCtx, LCtx, CC, CallOpts, Idx);
658 break;
659 }
660 case CXXConstructExpr::CK_VirtualBase: {
661 // Make sure we are not calling virtual base class initializers twice.
662 // Only the most-derived object should initialize virtual base classes.
663 const auto *OuterCtor = dyn_cast_or_null<CXXConstructExpr>(
664 LCtx->getStackFrame()->getCallSite());
665 assert((static_cast <bool> ((!OuterCtor || OuterCtor->getConstructionKind
() == CXXConstructExpr::CK_Complete || OuterCtor->getConstructionKind
() == CXXConstructExpr::CK_Delegating) && ("This virtual base should have already been initialized by "
"the most derived class!")) ? void (0) : __assert_fail ("(!OuterCtor || OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Complete || OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Delegating) && (\"This virtual base should have already been initialized by \" \"the most derived class!\")"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 670, __extension__
__PRETTY_FUNCTION__))
666 (!OuterCtor ||(static_cast <bool> ((!OuterCtor || OuterCtor->getConstructionKind
() == CXXConstructExpr::CK_Complete || OuterCtor->getConstructionKind
() == CXXConstructExpr::CK_Delegating) && ("This virtual base should have already been initialized by "
"the most derived class!")) ? void (0) : __assert_fail ("(!OuterCtor || OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Complete || OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Delegating) && (\"This virtual base should have already been initialized by \" \"the most derived class!\")"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 670, __extension__
__PRETTY_FUNCTION__))
667 OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Complete ||(static_cast <bool> ((!OuterCtor || OuterCtor->getConstructionKind
() == CXXConstructExpr::CK_Complete || OuterCtor->getConstructionKind
() == CXXConstructExpr::CK_Delegating) && ("This virtual base should have already been initialized by "
"the most derived class!")) ? void (0) : __assert_fail ("(!OuterCtor || OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Complete || OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Delegating) && (\"This virtual base should have already been initialized by \" \"the most derived class!\")"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 670, __extension__
__PRETTY_FUNCTION__))
668 OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Delegating) &&(static_cast <bool> ((!OuterCtor || OuterCtor->getConstructionKind
() == CXXConstructExpr::CK_Complete || OuterCtor->getConstructionKind
() == CXXConstructExpr::CK_Delegating) && ("This virtual base should have already been initialized by "
"the most derived class!")) ? void (0) : __assert_fail ("(!OuterCtor || OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Complete || OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Delegating) && (\"This virtual base should have already been initialized by \" \"the most derived class!\")"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 670, __extension__
__PRETTY_FUNCTION__))
669 ("This virtual base should have already been initialized by "(static_cast <bool> ((!OuterCtor || OuterCtor->getConstructionKind
() == CXXConstructExpr::CK_Complete || OuterCtor->getConstructionKind
() == CXXConstructExpr::CK_Delegating) && ("This virtual base should have already been initialized by "
"the most derived class!")) ? void (0) : __assert_fail ("(!OuterCtor || OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Complete || OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Delegating) && (\"This virtual base should have already been initialized by \" \"the most derived class!\")"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 670, __extension__
__PRETTY_FUNCTION__))
670 "the most derived class!"))(static_cast <bool> ((!OuterCtor || OuterCtor->getConstructionKind
() == CXXConstructExpr::CK_Complete || OuterCtor->getConstructionKind
() == CXXConstructExpr::CK_Delegating) && ("This virtual base should have already been initialized by "
"the most derived class!")) ? void (0) : __assert_fail ("(!OuterCtor || OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Complete || OuterCtor->getConstructionKind() == CXXConstructExpr::CK_Delegating) && (\"This virtual base should have already been initialized by \" \"the most derived class!\")"
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 670, __extension__
__PRETTY_FUNCTION__))
;
671 (void)OuterCtor;
672 [[fallthrough]];
673 }
674 case CXXConstructExpr::CK_NonVirtualBase:
675 // In C++17, classes with non-virtual bases may be aggregates, so they would
676 // be initialized as aggregates without a constructor call, so we may have
677 // a base class constructed directly into an initializer list without
678 // having the derived-class constructor call on the previous stack frame.
679 // Initializer lists may be nested into more initializer lists that
680 // correspond to surrounding aggregate initializations.
681 // FIXME: For now this code essentially bails out. We need to find the
682 // correct target region and set it.
683 // FIXME: Instead of relying on the ParentMap, we should have the
684 // trigger-statement (InitListExpr in this case) passed down from CFG or
685 // otherwise always available during construction.
686 if (isa_and_nonnull<InitListExpr>(LCtx->getParentMap().getParent(E))) {
687 MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
688 Target = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx));
689 CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;
690 break;
691 }
692 [[fallthrough]];
693 case CXXConstructExpr::CK_Delegating: {
694 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
695 Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
696 LCtx->getStackFrame());
697 SVal ThisVal = State->getSVal(ThisPtr);
698
699 if (CK == CXXConstructExpr::CK_Delegating) {
700 Target = ThisVal;
701 } else {
702 // Cast to the base type.
703 bool IsVirtual = (CK == CXXConstructExpr::CK_VirtualBase);
704 SVal BaseVal =
705 getStoreManager().evalDerivedToBase(ThisVal, E->getType(), IsVirtual);
706 Target = BaseVal;
707 }
708 break;
709 }
710 }
711
712 if (State != Pred->getState()) {
713 static SimpleProgramPointTag T("ExprEngine",
714 "Prepare for object construction");
715 ExplodedNodeSet DstPrepare;
716 StmtNodeBuilder BldrPrepare(Pred, DstPrepare, *currBldrCtx);
717 BldrPrepare.generateNode(E, Pred, State, &T, ProgramPoint::PreStmtKind);
718 assert(DstPrepare.size() <= 1)(static_cast <bool> (DstPrepare.size() <= 1) ? void (
0) : __assert_fail ("DstPrepare.size() <= 1", "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp"
, 718, __extension__ __PRETTY_FUNCTION__))
;
719 if (DstPrepare.size() == 0)
720 return;
721 Pred = *BldrPrepare.begin();
722 }
723
724 const MemRegion *TargetRegion = Target.getAsRegion();
725 CallEventManager &CEMgr = getStateManager().getCallEventManager();
726 CallEventRef<> Call =
727 CIE ? (CallEventRef<>)CEMgr.getCXXInheritedConstructorCall(
728 CIE, TargetRegion, State, LCtx)
729 : (CallEventRef<>)CEMgr.getCXXConstructorCall(
730 CE, TargetRegion, State, LCtx);
731
732 ExplodedNodeSet DstPreVisit;
733 getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, E, *this);
734
735 ExplodedNodeSet PreInitialized;
736 if (CE) {
737 // FIXME: Is it possible and/or useful to do this before PreStmt?
738 StmtNodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx);
739 for (ExplodedNodeSet::iterator I = DstPreVisit.begin(),
740 E = DstPreVisit.end();
741 I != E; ++I) {
742 ProgramStateRef State = (*I)->getState();
743 if (CE->requiresZeroInitialization()) {
744 // FIXME: Once we properly handle constructors in new-expressions, we'll
745 // need to invalidate the region before setting a default value, to make
746 // sure there aren't any lingering bindings around. This probably needs
747 // to happen regardless of whether or not the object is zero-initialized
748 // to handle random fields of a placement-initialized object picking up
749 // old bindings. We might only want to do it when we need to, though.
750 // FIXME: This isn't actually correct for arrays -- we need to zero-
751 // initialize the entire array, not just the first element -- but our
752 // handling of arrays everywhere else is weak as well, so this shouldn't
753 // actually make things worse. Placement new makes this tricky as well,
754 // since it's then possible to be initializing one part of a multi-
755 // dimensional array.
756 State = State->bindDefaultZero(Target, LCtx);
757 }
758
759 Bldr.generateNode(CE, *I, State, /*tag=*/nullptr,
760 ProgramPoint::PreStmtKind);
761 }
762 } else {
763 PreInitialized = DstPreVisit;
764 }
765
766 ExplodedNodeSet DstPreCall;
767 getCheckerManager().runCheckersForPreCall(DstPreCall, PreInitialized,
768 *Call, *this);
769
770 ExplodedNodeSet DstEvaluated;
771
772 if (CE && CE->getConstructor()->isTrivial() &&
773 CE->getConstructor()->isCopyOrMoveConstructor() &&
774 !CallOpts.IsArrayCtorOrDtor) {
775 StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx);
776 // FIXME: Handle other kinds of trivial constructors as well.
777 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
778 I != E; ++I)
779 performTrivialCopy(Bldr, *I, *Call);
780
781 } else {
782 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
783 I != E; ++I)
784 getCheckerManager().runCheckersForEvalCall(DstEvaluated, *I, *Call, *this,
785 CallOpts);
786 }
787
788 // If the CFG was constructed without elements for temporary destructors
789 // and the just-called constructor created a temporary object then
790 // stop exploration if the temporary object has a noreturn constructor.
791 // This can lose coverage because the destructor, if it were present
792 // in the CFG, would be called at the end of the full expression or
793 // later (for life-time extended temporaries) -- but avoids infeasible
794 // paths when no-return temporary destructors are used for assertions.
795 ExplodedNodeSet DstEvaluatedPostProcessed;
796 StmtNodeBuilder Bldr(DstEvaluated, DstEvaluatedPostProcessed, *currBldrCtx);
797 const AnalysisDeclContext *ADC = LCtx->getAnalysisDeclContext();
798 if (!ADC->getCFGBuildOptions().AddTemporaryDtors) {
799 if (llvm::isa_and_nonnull<CXXTempObjectRegion>(TargetRegion) &&
800 cast<CXXConstructorDecl>(Call->getDecl())
801 ->getParent()
802 ->isAnyDestructorNoReturn()) {
803
804 // If we've inlined the constructor, then DstEvaluated would be empty.
805 // In this case we still want a sink, which could be implemented
806 // in processCallExit. But we don't have that implemented at the moment,
807 // so if you hit this assertion, see if you can avoid inlining
808 // the respective constructor when analyzer-config cfg-temporary-dtors
809 // is set to false.
810 // Otherwise there's nothing wrong with inlining such constructor.
811 assert(!DstEvaluated.empty() &&(static_cast <bool> (!DstEvaluated.empty() && "We should not have inlined this constructor!"
) ? void (0) : __assert_fail ("!DstEvaluated.empty() && \"We should not have inlined this constructor!\""
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 812, __extension__
__PRETTY_FUNCTION__))
812 "We should not have inlined this constructor!")(static_cast <bool> (!DstEvaluated.empty() && "We should not have inlined this constructor!"
) ? void (0) : __assert_fail ("!DstEvaluated.empty() && \"We should not have inlined this constructor!\""
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 812, __extension__
__PRETTY_FUNCTION__))
;
813
814 for (ExplodedNode *N : DstEvaluated) {
815 Bldr.generateSink(E, N, N->getState());
816 }
817
818 // There is no need to run the PostCall and PostStmt checker
819 // callbacks because we just generated sinks on all nodes in th
820 // frontier.
821 return;
822 }
823 }
824
825 ExplodedNodeSet DstPostArgumentCleanup;
826 for (ExplodedNode *I : DstEvaluatedPostProcessed)
827 finishArgumentConstruction(DstPostArgumentCleanup, I, *Call);
828
829 // If there were other constructors called for object-type arguments
830 // of this constructor, clean them up.
831 ExplodedNodeSet DstPostCall;
832 getCheckerManager().runCheckersForPostCall(DstPostCall,
833 DstPostArgumentCleanup,
834 *Call, *this);
835 getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, E, *this);
836}
837
838void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
839 ExplodedNode *Pred,
840 ExplodedNodeSet &Dst) {
841 handleConstructor(CE, Pred, Dst);
842}
843
844void ExprEngine::VisitCXXInheritedCtorInitExpr(
845 const CXXInheritedCtorInitExpr *CE, ExplodedNode *Pred,
846 ExplodedNodeSet &Dst) {
847 handleConstructor(CE, Pred, Dst);
848}
849
850void ExprEngine::VisitCXXDestructor(QualType ObjectType,
851 const MemRegion *Dest,
852 const Stmt *S,
853 bool IsBaseDtor,
854 ExplodedNode *Pred,
855 ExplodedNodeSet &Dst,
856 EvalCallOptions &CallOpts) {
857 assert(S && "A destructor without a trigger!")(static_cast <bool> (S && "A destructor without a trigger!"
) ? void (0) : __assert_fail ("S && \"A destructor without a trigger!\""
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 857, __extension__
__PRETTY_FUNCTION__))
;
858 const LocationContext *LCtx = Pred->getLocationContext();
859 ProgramStateRef State = Pred->getState();
860
861 const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl();
862 assert(RecordDecl && "Only CXXRecordDecls should have destructors")(static_cast <bool> (RecordDecl && "Only CXXRecordDecls should have destructors"
) ? void (0) : __assert_fail ("RecordDecl && \"Only CXXRecordDecls should have destructors\""
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 862, __extension__
__PRETTY_FUNCTION__))
;
863 const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor();
864 // FIXME: There should always be a Decl, otherwise the destructor call
865 // shouldn't have been added to the CFG in the first place.
866 if (!DtorDecl) {
867 // Skip the invalid destructor. We cannot simply return because
868 // it would interrupt the analysis instead.
869 static SimpleProgramPointTag T("ExprEngine", "SkipInvalidDestructor");
870 // FIXME: PostImplicitCall with a null decl may crash elsewhere anyway.
871 PostImplicitCall PP(/*Decl=*/nullptr, S->getEndLoc(), LCtx, &T);
872 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
873 Bldr.generateNode(PP, Pred->getState(), Pred);
874 return;
875 }
876
877 if (!Dest) {
878 // We're trying to destroy something that is not a region. This may happen
879 // for a variety of reasons (unknown target region, concrete integer instead
880 // of target region, etc.). The current code makes an attempt to recover.
881 // FIXME: We probably don't really need to recover when we're dealing
882 // with concrete integers specifically.
883 CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;
884 if (const Expr *E = dyn_cast_or_null<Expr>(S)) {
885 Dest = MRMgr.getCXXTempObjectRegion(E, Pred->getLocationContext());
886 } else {
887 static SimpleProgramPointTag T("ExprEngine", "SkipInvalidDestructor");
888 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
889 Bldr.generateSink(Pred->getLocation().withTag(&T),
890 Pred->getState(), Pred);
891 return;
892 }
893 }
894
895 CallEventManager &CEMgr = getStateManager().getCallEventManager();
896 CallEventRef<CXXDestructorCall> Call =
897 CEMgr.getCXXDestructorCall(DtorDecl, S, Dest, IsBaseDtor, State, LCtx);
898
899 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
900 Call->getSourceRange().getBegin(),
901 "Error evaluating destructor");
902
903 ExplodedNodeSet DstPreCall;
904 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
905 *Call, *this);
906
907 ExplodedNodeSet DstInvalidated;
908 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);
909 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
910 I != E; ++I)
911 defaultEvalCall(Bldr, *I, *Call, CallOpts);
912
913 getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,
914 *Call, *this);
915}
916
917void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
918 ExplodedNode *Pred,
919 ExplodedNodeSet &Dst) {
920 ProgramStateRef State = Pred->getState();
921 const LocationContext *LCtx = Pred->getLocationContext();
922 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
923 CNE->getBeginLoc(),
924 "Error evaluating New Allocator Call");
925 CallEventManager &CEMgr = getStateManager().getCallEventManager();
926 CallEventRef<CXXAllocatorCall> Call =
927 CEMgr.getCXXAllocatorCall(CNE, State, LCtx);
928
929 ExplodedNodeSet DstPreCall;
930 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,
931 *Call, *this);
932
933 ExplodedNodeSet DstPostCall;
934 StmtNodeBuilder CallBldr(DstPreCall, DstPostCall, *currBldrCtx);
935 for (ExplodedNode *I : DstPreCall) {
936 // FIXME: Provide evalCall for checkers?
937 defaultEvalCall(CallBldr, I, *Call);
938 }
939 // If the call is inlined, DstPostCall will be empty and we bail out now.
940
941 // Store return value of operator new() for future use, until the actual
942 // CXXNewExpr gets processed.
943 ExplodedNodeSet DstPostValue;
944 StmtNodeBuilder ValueBldr(DstPostCall, DstPostValue, *currBldrCtx);
945 for (ExplodedNode *I : DstPostCall) {
946 // FIXME: Because CNE serves as the "call site" for the allocator (due to
947 // lack of a better expression in the AST), the conjured return value symbol
948 // is going to be of the same type (C++ object pointer type). Technically
949 // this is not correct because the operator new's prototype always says that
950 // it returns a 'void *'. So we should change the type of the symbol,
951 // and then evaluate the cast over the symbolic pointer from 'void *' to
952 // the object pointer type. But without changing the symbol's type it
953 // is breaking too much to evaluate the no-op symbolic cast over it, so we
954 // skip it for now.
955 ProgramStateRef State = I->getState();
956 SVal RetVal = State->getSVal(CNE, LCtx);
957 // [basic.stc.dynamic.allocation] (on the return value of an allocation
958 // function):
959 // "The order, contiguity, and initial value of storage allocated by
960 // successive calls to an allocation function are unspecified."
961 State = State->bindDefaultInitial(RetVal, UndefinedVal{}, LCtx);
962
963 // If this allocation function is not declared as non-throwing, failures
964 // /must/ be signalled by exceptions, and thus the return value will never
965 // be NULL. -fno-exceptions does not influence this semantics.
966 // FIXME: GCC has a -fcheck-new option, which forces it to consider the case
967 // where new can return NULL. If we end up supporting that option, we can
968 // consider adding a check for it here.
969 // C++11 [basic.stc.dynamic.allocation]p3.
970 if (const FunctionDecl *FD = CNE->getOperatorNew()) {
971 QualType Ty = FD->getType();
972 if (const auto *ProtoType = Ty->getAs<FunctionProtoType>())
973 if (!ProtoType->isNothrow())
974 State = State->assume(RetVal.castAs<DefinedOrUnknownSVal>(), true);
975 }
976
977 ValueBldr.generateNode(
978 CNE, I, addObjectUnderConstruction(State, CNE, LCtx, RetVal));
979 }
980
981 ExplodedNodeSet DstPostPostCallCallback;
982 getCheckerManager().runCheckersForPostCall(DstPostPostCallCallback,
983 DstPostValue, *Call, *this);
984 for (ExplodedNode *I : DstPostPostCallCallback) {
985 getCheckerManager().runCheckersForNewAllocator(*Call, Dst, I, *this);
986 }
987}
988
989void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
990 ExplodedNodeSet &Dst) {
991 // FIXME: Much of this should eventually migrate to CXXAllocatorCall.
992 // Also, we need to decide how allocators actually work -- they're not
993 // really part of the CXXNewExpr because they happen BEFORE the
994 // CXXConstructExpr subexpression. See PR12014 for some discussion.
995
996 unsigned blockCount = currBldrCtx->blockCount();
997 const LocationContext *LCtx = Pred->getLocationContext();
998 SVal symVal = UnknownVal();
999 FunctionDecl *FD = CNE->getOperatorNew();
1000
1001 bool IsStandardGlobalOpNewFunction =
1002 FD->isReplaceableGlobalAllocationFunction();
1003
1004 ProgramStateRef State = Pred->getState();
1005
1006 // Retrieve the stored operator new() return value.
1007 if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
1008 symVal = *getObjectUnderConstruction(State, CNE, LCtx);
1009 State = finishObjectConstruction(State, CNE, LCtx);
1010 }
1011
1012 // We assume all standard global 'operator new' functions allocate memory in
1013 // heap. We realize this is an approximation that might not correctly model
1014 // a custom global allocator.
1015 if (symVal.isUnknown()) {
1016 if (IsStandardGlobalOpNewFunction)
1017 symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount);
1018 else
1019 symVal = svalBuilder.conjureSymbolVal(nullptr, CNE, LCtx, CNE->getType(),
1020 blockCount);
1021 }
1022
1023 CallEventManager &CEMgr = getStateManager().getCallEventManager();
1024 CallEventRef<CXXAllocatorCall> Call =
1025 CEMgr.getCXXAllocatorCall(CNE, State, LCtx);
1026
1027 if (!AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
1028 // Invalidate placement args.
1029 // FIXME: Once we figure out how we want allocators to work,
1030 // we should be using the usual pre-/(default-)eval-/post-call checkers
1031 // here.
1032 State = Call->invalidateRegions(blockCount);
1033 if (!State)
1034 return;
1035
1036 // If this allocation function is not declared as non-throwing, failures
1037 // /must/ be signalled by exceptions, and thus the return value will never
1038 // be NULL. -fno-exceptions does not influence this semantics.
1039 // FIXME: GCC has a -fcheck-new option, which forces it to consider the case
1040 // where new can return NULL. If we end up supporting that option, we can
1041 // consider adding a check for it here.
1042 // C++11 [basic.stc.dynamic.allocation]p3.
1043 if (const auto *ProtoType = FD->getType()->getAs<FunctionProtoType>())
1044 if (!ProtoType->isNothrow())
1045 if (auto dSymVal = symVal.getAs<DefinedOrUnknownSVal>())
1046 State = State->assume(*dSymVal, true);
1047 }
1048
1049 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1050
1051 SVal Result = symVal;
1052
1053 if (CNE->isArray()) {
1054
1055 if (const auto *NewReg = cast_or_null<SubRegion>(symVal.getAsRegion())) {
1056 // If each element is initialized by their default constructor, the field
1057 // values are properly placed inside the required region, however if an
1058 // initializer list is used, this doesn't happen automatically.
1059 auto *Init = CNE->getInitializer();
1060 bool isInitList = isa_and_nonnull<InitListExpr>(Init);
1061
1062 QualType ObjTy =
1063 isInitList ? Init->getType() : CNE->getType()->getPointeeType();
1064 const ElementRegion *EleReg =
1065 MRMgr.getElementRegion(ObjTy, svalBuilder.makeArrayIndex(0), NewReg,
1066 svalBuilder.getContext());
1067 Result = loc::MemRegionVal(EleReg);
1068
1069 // If the array is list initialized, we bind the initializer list to the
1070 // memory region here, otherwise we would lose it.
1071 if (isInitList) {
1072 Bldr.takeNodes(Pred);
1073 Pred = Bldr.generateNode(CNE, Pred, State);
1074
1075 SVal V = State->getSVal(Init, LCtx);
1076 ExplodedNodeSet evaluated;
1077 evalBind(evaluated, CNE, Pred, Result, V, true);
1078
1079 Bldr.takeNodes(Pred);
1080 Bldr.addNodes(evaluated);
1081
1082 Pred = *evaluated.begin();
1083 State = Pred->getState();
1084 }
1085 }
1086
1087 State = State->BindExpr(CNE, Pred->getLocationContext(), Result);
1088 Bldr.generateNode(CNE, Pred, State);
1089 return;
1090 }
1091
1092 // FIXME: Once we have proper support for CXXConstructExprs inside
1093 // CXXNewExpr, we need to make sure that the constructed object is not
1094 // immediately invalidated here. (The placement call should happen before
1095 // the constructor call anyway.)
1096 if (FD->isReservedGlobalPlacementOperator()) {
1097 // Non-array placement new should always return the placement location.
1098 SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);
1099 Result = svalBuilder.evalCast(PlacementLoc, CNE->getType(),
1100 CNE->getPlacementArg(0)->getType());
1101 }
1102
1103 // Bind the address of the object, then check to see if we cached out.
1104 State = State->BindExpr(CNE, LCtx, Result);
1105 ExplodedNode *NewN = Bldr.generateNode(CNE, Pred, State);
1106 if (!NewN)
1107 return;
1108
1109 // If the type is not a record, we won't have a CXXConstructExpr as an
1110 // initializer. Copy the value over.
1111 if (const Expr *Init = CNE->getInitializer()) {
1112 if (!isa<CXXConstructExpr>(Init)) {
1113 assert(Bldr.getResults().size() == 1)(static_cast <bool> (Bldr.getResults().size() == 1) ? void
(0) : __assert_fail ("Bldr.getResults().size() == 1", "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp"
, 1113, __extension__ __PRETTY_FUNCTION__))
;
1114 Bldr.takeNodes(NewN);
1115 evalBind(Dst, CNE, NewN, Result, State->getSVal(Init, LCtx),
1116 /*FirstInit=*/IsStandardGlobalOpNewFunction);
1117 }
1118 }
1119}
1120
1121void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
1122 ExplodedNode *Pred, ExplodedNodeSet &Dst) {
1123
1124 CallEventManager &CEMgr = getStateManager().getCallEventManager();
1125 CallEventRef<CXXDeallocatorCall> Call = CEMgr.getCXXDeallocatorCall(
1126 CDE, Pred->getState(), Pred->getLocationContext());
1127
1128 ExplodedNodeSet DstPreCall;
1129 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, *Call, *this);
1130 ExplodedNodeSet DstPostCall;
1131
1132 if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
1133 StmtNodeBuilder Bldr(DstPreCall, DstPostCall, *currBldrCtx);
1134 for (ExplodedNode *I : DstPreCall) {
1135 defaultEvalCall(Bldr, I, *Call);
1136 }
1137 } else {
1138 DstPostCall = DstPreCall;
1139 }
1140 getCheckerManager().runCheckersForPostCall(Dst, DstPostCall, *Call, *this);
1141}
1142
1143void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred,
1144 ExplodedNodeSet &Dst) {
1145 const VarDecl *VD = CS->getExceptionDecl();
1146 if (!VD) {
1147 Dst.Add(Pred);
1148 return;
1149 }
1150
1151 const LocationContext *LCtx = Pred->getLocationContext();
1152 SVal V = svalBuilder.conjureSymbolVal(CS, LCtx, VD->getType(),
1153 currBldrCtx->blockCount());
1154 ProgramStateRef state = Pred->getState();
1155 state = state->bindLoc(state->getLValue(VD, LCtx), V, LCtx);
1156
1157 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1158 Bldr.generateNode(CS, Pred, state);
1159}
1160
1161void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
1162 ExplodedNodeSet &Dst) {
1163 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1164
1165 // Get the this object region from StoreManager.
1166 const LocationContext *LCtx = Pred->getLocationContext();
1167 const MemRegion *R =
1168 svalBuilder.getRegionManager().getCXXThisRegion(
1169 getContext().getCanonicalType(TE->getType()),
1170 LCtx);
1171
1172 ProgramStateRef state = Pred->getState();
1173 SVal V = state->getSVal(loc::MemRegionVal(R));
1174 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
1175}
1176
1177void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
1178 ExplodedNodeSet &Dst) {
1179 const LocationContext *LocCtxt = Pred->getLocationContext();
1180
1181 // Get the region of the lambda itself.
1182 const MemRegion *R = svalBuilder.getRegionManager().getCXXTempObjectRegion(
1183 LE, LocCtxt);
1184 SVal V = loc::MemRegionVal(R);
1185
1186 ProgramStateRef State = Pred->getState();
1187
1188 // If we created a new MemRegion for the lambda, we should explicitly bind
1189 // the captures.
1190 unsigned Idx = 0;
1191 CXXRecordDecl::field_iterator CurField = LE->getLambdaClass()->field_begin();
1192 for (LambdaExpr::const_capture_init_iterator i = LE->capture_init_begin(),
1193 e = LE->capture_init_end();
1194 i != e; ++i, ++CurField, ++Idx) {
1195 FieldDecl *FieldForCapture = *CurField;
1196 SVal FieldLoc = State->getLValue(FieldForCapture, V);
1197
1198 SVal InitVal;
1199 if (!FieldForCapture->hasCapturedVLAType()) {
1200 const Expr *InitExpr = *i;
1201
1202 assert(InitExpr && "Capture missing initialization expression")(static_cast <bool> (InitExpr && "Capture missing initialization expression"
) ? void (0) : __assert_fail ("InitExpr && \"Capture missing initialization expression\""
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 1202, __extension__
__PRETTY_FUNCTION__))
;
1203
1204 // Capturing a 0 length array is a no-op, so we ignore it to get a more
1205 // accurate analysis. If it's not ignored, it would set the default
1206 // binding of the lambda to 'Unknown', which can lead to falsely detecting
1207 // 'Uninitialized' values as 'Unknown' and not reporting a warning.
1208 const auto FTy = FieldForCapture->getType();
1209 if (FTy->isConstantArrayType() &&
1210 getContext().getConstantArrayElementCount(
1211 getContext().getAsConstantArrayType(FTy)) == 0)
1212 continue;
1213
1214 // With C++17 copy elision the InitExpr can be anything, so instead of
1215 // pattern matching all cases, we simple check if the current field is
1216 // under construction or not, regardless what it's InitExpr is.
1217 if (const auto OUC =
1218 getObjectUnderConstruction(State, {LE, Idx}, LocCtxt)) {
1219 InitVal = State->getSVal(OUC->getAsRegion());
1220
1221 State = finishObjectConstruction(State, {LE, Idx}, LocCtxt);
1222 } else
1223 InitVal = State->getSVal(InitExpr, LocCtxt);
1224
1225 } else {
1226
1227 assert(!getObjectUnderConstruction(State, {LE, Idx}, LocCtxt) &&(static_cast <bool> (!getObjectUnderConstruction(State,
{LE, Idx}, LocCtxt) && "VLA capture by value is a compile time error!"
) ? void (0) : __assert_fail ("!getObjectUnderConstruction(State, {LE, Idx}, LocCtxt) && \"VLA capture by value is a compile time error!\""
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 1228, __extension__
__PRETTY_FUNCTION__))
1228 "VLA capture by value is a compile time error!")(static_cast <bool> (!getObjectUnderConstruction(State,
{LE, Idx}, LocCtxt) && "VLA capture by value is a compile time error!"
) ? void (0) : __assert_fail ("!getObjectUnderConstruction(State, {LE, Idx}, LocCtxt) && \"VLA capture by value is a compile time error!\""
, "clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp", 1228, __extension__
__PRETTY_FUNCTION__))
;
1229
1230 // The field stores the length of a captured variable-length array.
1231 // These captures don't have initialization expressions; instead we
1232 // get the length from the VLAType size expression.
1233 Expr *SizeExpr = FieldForCapture->getCapturedVLAType()->getSizeExpr();
1234 InitVal = State->getSVal(SizeExpr, LocCtxt);
1235 }
1236
1237 State = State->bindLoc(FieldLoc, InitVal, LocCtxt);
1238 }
1239
1240 // Decay the Loc into an RValue, because there might be a
1241 // MaterializeTemporaryExpr node above this one which expects the bound value
1242 // to be an RValue.
1243 SVal LambdaRVal = State->getSVal(R);
1244
1245 ExplodedNodeSet Tmp;
1246 StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
1247 // FIXME: is this the right program point kind?
1248 Bldr.generateNode(LE, Pred,
1249 State->BindExpr(LE, LocCtxt, LambdaRVal),
1250 nullptr, ProgramPoint::PostLValueKind);
1251
1252 // FIXME: Move all post/pre visits to ::Visit().
1253 getCheckerManager().runCheckersForPostStmt(Dst, Tmp, LE, *this);
1254}

/build/source/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h

1//===- ExprEngine.h - Path-Sensitive Expression-Level Dataflow --*- 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 a meta-engine for path-sensitive dataflow analysis that
10// is built on CoreEngine, but provides the boilerplate to execute transfer
11// functions and build the ExplodedGraph at the expression level.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H
16#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H
17
18#include "clang/AST/Expr.h"
19#include "clang/AST/Type.h"
20#include "clang/Analysis/CFG.h"
21#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
22#include "clang/Analysis/ProgramPoint.h"
23#include "clang/Basic/LLVM.h"
24#include "clang/StaticAnalyzer/Core/CheckerManager.h"
25#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
26#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
27#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
28#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
29#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
30#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
31#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
32#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
33#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
34#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
35#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
36#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
37#include "llvm/ADT/ArrayRef.h"
38#include <cassert>
39#include <utility>
40
41namespace clang {
42
43class AnalysisDeclContextManager;
44class AnalyzerOptions;
45class ASTContext;
46class CFGBlock;
47class CFGElement;
48class ConstructionContext;
49class CXXBindTemporaryExpr;
50class CXXCatchStmt;
51class CXXConstructExpr;
52class CXXDeleteExpr;
53class CXXNewExpr;
54class CXXThisExpr;
55class Decl;
56class DeclStmt;
57class GCCAsmStmt;
58class LambdaExpr;
59class LocationContext;
60class MaterializeTemporaryExpr;
61class MSAsmStmt;
62class NamedDecl;
63class ObjCAtSynchronizedStmt;
64class ObjCForCollectionStmt;
65class ObjCIvarRefExpr;
66class ObjCMessageExpr;
67class ReturnStmt;
68class Stmt;
69
70namespace cross_tu {
71
72class CrossTranslationUnitContext;
73
74} // namespace cross_tu
75
76namespace ento {
77
78class AnalysisManager;
79class BasicValueFactory;
80class CallEvent;
81class CheckerManager;
82class ConstraintManager;
83class ExplodedNodeSet;
84class ExplodedNode;
85class IndirectGotoNodeBuilder;
86class MemRegion;
87struct NodeBuilderContext;
88class NodeBuilderWithSinks;
89class ProgramState;
90class ProgramStateManager;
91class RegionAndSymbolInvalidationTraits;
92class SymbolManager;
93class SwitchNodeBuilder;
94
95/// Hints for figuring out of a call should be inlined during evalCall().
96struct EvalCallOptions {
97 /// This call is a constructor or a destructor for which we do not currently
98 /// compute the this-region correctly.
99 bool IsCtorOrDtorWithImproperlyModeledTargetRegion = false;
100
101 /// This call is a constructor or a destructor for a single element within
102 /// an array, a part of array construction or destruction.
103 bool IsArrayCtorOrDtor = false;
104
105 /// This call is a constructor or a destructor of a temporary value.
106 bool IsTemporaryCtorOrDtor = false;
107
108 /// This call is a constructor for a temporary that is lifetime-extended
109 /// by binding it to a reference-type field within an aggregate,
110 /// for example 'A { const C &c; }; A a = { C() };'
111 bool IsTemporaryLifetimeExtendedViaAggregate = false;
112
113 /// This call is a pre-C++17 elidable constructor that we failed to elide
114 /// because we failed to compute the target region into which
115 /// this constructor would have been ultimately elided. Analysis that
116 /// we perform in this case is still correct but it behaves differently,
117 /// as if copy elision is disabled.
118 bool IsElidableCtorThatHasNotBeenElided = false;
119
120 EvalCallOptions() {}
121};
122
123class ExprEngine {
124 void anchor();
125
126public:
127 /// The modes of inlining, which override the default analysis-wide settings.
128 enum InliningModes {
129 /// Follow the default settings for inlining callees.
130 Inline_Regular = 0,
131
132 /// Do minimal inlining of callees.
133 Inline_Minimal = 0x1
134 };
135
136private:
137 cross_tu::CrossTranslationUnitContext &CTU;
138 bool IsCTUEnabled;
139
140 AnalysisManager &AMgr;
141
142 AnalysisDeclContextManager &AnalysisDeclContexts;
143
144 CoreEngine Engine;
145
146 /// G - the simulation graph.
147 ExplodedGraph &G;
148
149 /// StateMgr - Object that manages the data for all created states.
150 ProgramStateManager StateMgr;
151
152 /// SymMgr - Object that manages the symbol information.
153 SymbolManager &SymMgr;
154
155 /// MRMgr - MemRegionManager object that creates memory regions.
156 MemRegionManager &MRMgr;
157
158 /// svalBuilder - SValBuilder object that creates SVals from expressions.
159 SValBuilder &svalBuilder;
160
161 unsigned int currStmtIdx = 0;
162 const NodeBuilderContext *currBldrCtx = nullptr;
163
164 /// Helper object to determine if an Objective-C message expression
165 /// implicitly never returns.
166 ObjCNoReturn ObjCNoRet;
167
168 /// The BugReporter associated with this engine. It is important that
169 /// this object be placed at the very end of member variables so that its
170 /// destructor is called before the rest of the ExprEngine is destroyed.
171 PathSensitiveBugReporter BR;
172
173 /// The functions which have been analyzed through inlining. This is owned by
174 /// AnalysisConsumer. It can be null.
175 SetOfConstDecls *VisitedCallees;
176
177 /// The flag, which specifies the mode of inlining for the engine.
178 InliningModes HowToInline;
179
180public:
181 ExprEngine(cross_tu::CrossTranslationUnitContext &CTU, AnalysisManager &mgr,
182 SetOfConstDecls *VisitedCalleesIn,
183 FunctionSummariesTy *FS, InliningModes HowToInlineIn);
184
185 virtual ~ExprEngine() = default;
186
187 /// Returns true if there is still simulation state on the worklist.
188 bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
189 return Engine.ExecuteWorkList(L, Steps, nullptr);
190 }
191
192 /// Execute the work list with an initial state. Nodes that reaches the exit
193 /// of the function are added into the Dst set, which represent the exit
194 /// state of the function call. Returns true if there is still simulation
195 /// state on the worklist.
196 bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
197 ProgramStateRef InitState,
198 ExplodedNodeSet &Dst) {
199 return Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
200 }
201
202 /// getContext - Return the ASTContext associated with this analysis.
203 ASTContext &getContext() const { return AMgr.getASTContext(); }
204
205 AnalysisManager &getAnalysisManager() { return AMgr; }
206
207 AnalysisDeclContextManager &getAnalysisDeclContextManager() {
208 return AMgr.getAnalysisDeclContextManager();
209 }
210
211 CheckerManager &getCheckerManager() const {
212 return *AMgr.getCheckerManager();
213 }
214
215 SValBuilder &getSValBuilder() { return svalBuilder; }
216
217 BugReporter &getBugReporter() { return BR; }
218
219 cross_tu::CrossTranslationUnitContext *
220 getCrossTranslationUnitContext() {
221 return &CTU;
222 }
223
224 const NodeBuilderContext &getBuilderContext() {
225 assert(currBldrCtx)(static_cast <bool> (currBldrCtx) ? void (0) : __assert_fail
("currBldrCtx", "clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
, 225, __extension__ __PRETTY_FUNCTION__))
;
226 return *currBldrCtx;
227 }
228
229 const Stmt *getStmt() const;
230
231 const LocationContext *getRootLocationContext() const {
232 assert(G.roots_begin() != G.roots_end())(static_cast <bool> (G.roots_begin() != G.roots_end()) ?
void (0) : __assert_fail ("G.roots_begin() != G.roots_end()"
, "clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
, 232, __extension__ __PRETTY_FUNCTION__))
;
233 return (*G.roots_begin())->getLocation().getLocationContext();
234 }
235
236 void GenerateAutoTransition(ExplodedNode *N);
237 void enqueueEndOfPath(ExplodedNodeSet &S);
238 void GenerateCallExitNode(ExplodedNode *N);
239
240
241 /// Dump graph to the specified filename.
242 /// If filename is empty, generate a temporary one.
243 /// \return The filename the graph is written into.
244 std::string DumpGraph(bool trim = false, StringRef Filename="");
245
246 /// Dump the graph consisting of the given nodes to a specified filename.
247 /// Generate a temporary filename if it's not provided.
248 /// \return The filename the graph is written into.
249 std::string DumpGraph(ArrayRef<const ExplodedNode *> Nodes,
250 StringRef Filename = "");
251
252 /// Visualize the ExplodedGraph created by executing the simulation.
253 void ViewGraph(bool trim = false);
254
255 /// Visualize a trimmed ExplodedGraph that only contains paths to the given
256 /// nodes.
257 void ViewGraph(ArrayRef<const ExplodedNode *> Nodes);
258
259 /// getInitialState - Return the initial state used for the root vertex
260 /// in the ExplodedGraph.
261 ProgramStateRef getInitialState(const LocationContext *InitLoc);
262
263 ExplodedGraph &getGraph() { return G; }
264 const ExplodedGraph &getGraph() const { return G; }
265
266 /// Run the analyzer's garbage collection - remove dead symbols and
267 /// bindings from the state.
268 ///
269 /// Checkers can participate in this process with two callbacks:
270 /// \c checkLiveSymbols and \c checkDeadSymbols. See the CheckerDocumentation
271 /// class for more information.
272 ///
273 /// \param Node The predecessor node, from which the processing should start.
274 /// \param Out The returned set of output nodes.
275 /// \param ReferenceStmt The statement which is about to be processed.
276 /// Everything needed for this statement should be considered live.
277 /// A null statement means that everything in child LocationContexts
278 /// is dead.
279 /// \param LC The location context of the \p ReferenceStmt. A null location
280 /// context means that we have reached the end of analysis and that
281 /// all statements and local variables should be considered dead.
282 /// \param DiagnosticStmt Used as a location for any warnings that should
283 /// occur while removing the dead (e.g. leaks). By default, the
284 /// \p ReferenceStmt is used.
285 /// \param K Denotes whether this is a pre- or post-statement purge. This
286 /// must only be ProgramPoint::PostStmtPurgeDeadSymbolsKind if an
287 /// entire location context is being cleared, in which case the
288 /// \p ReferenceStmt must either be a ReturnStmt or \c NULL. Otherwise,
289 /// it must be ProgramPoint::PreStmtPurgeDeadSymbolsKind (the default)
290 /// and \p ReferenceStmt must be valid (non-null).
291 void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out,
292 const Stmt *ReferenceStmt, const LocationContext *LC,
293 const Stmt *DiagnosticStmt = nullptr,
294 ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind);
295
296 /// processCFGElement - Called by CoreEngine. Used to generate new successor
297 /// nodes by processing the 'effects' of a CFG element.
298 void processCFGElement(const CFGElement E, ExplodedNode *Pred,
299 unsigned StmtIdx, NodeBuilderContext *Ctx);
300
301 void ProcessStmt(const Stmt *S, ExplodedNode *Pred);
302
303 void ProcessLoopExit(const Stmt* S, ExplodedNode *Pred);
304
305 void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred);
306
307 void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred);
308
309 void ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred);
310
311 void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D,
312 ExplodedNode *Pred, ExplodedNodeSet &Dst);
313 void ProcessDeleteDtor(const CFGDeleteDtor D,
314 ExplodedNode *Pred, ExplodedNodeSet &Dst);
315 void ProcessBaseDtor(const CFGBaseDtor D,
316 ExplodedNode *Pred, ExplodedNodeSet &Dst);
317 void ProcessMemberDtor(const CFGMemberDtor D,
318 ExplodedNode *Pred, ExplodedNodeSet &Dst);
319 void ProcessTemporaryDtor(const CFGTemporaryDtor D,
320 ExplodedNode *Pred, ExplodedNodeSet &Dst);
321
322 /// Called by CoreEngine when processing the entrance of a CFGBlock.
323 void processCFGBlockEntrance(const BlockEdge &L,
324 NodeBuilderWithSinks &nodeBuilder,
325 ExplodedNode *Pred);
326
327 /// ProcessBranch - Called by CoreEngine. Used to generate successor
328 /// nodes by processing the 'effects' of a branch condition.
329 void processBranch(const Stmt *Condition,
330 NodeBuilderContext& BuilderCtx,
331 ExplodedNode *Pred,
332 ExplodedNodeSet &Dst,
333 const CFGBlock *DstT,
334 const CFGBlock *DstF);
335
336 /// Called by CoreEngine.
337 /// Used to generate successor nodes for temporary destructors depending
338 /// on whether the corresponding constructor was visited.
339 void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
340 NodeBuilderContext &BldCtx,
341 ExplodedNode *Pred, ExplodedNodeSet &Dst,
342 const CFGBlock *DstT,
343 const CFGBlock *DstF);
344
345 /// Called by CoreEngine. Used to processing branching behavior
346 /// at static initializers.
347 void processStaticInitializer(const DeclStmt *DS,
348 NodeBuilderContext& BuilderCtx,
349 ExplodedNode *Pred,
350 ExplodedNodeSet &Dst,
351 const CFGBlock *DstT,
352 const CFGBlock *DstF);
353
354 /// processIndirectGoto - Called by CoreEngine. Used to generate successor
355 /// nodes by processing the 'effects' of a computed goto jump.
356 void processIndirectGoto(IndirectGotoNodeBuilder& builder);
357
358 /// ProcessSwitch - Called by CoreEngine. Used to generate successor
359 /// nodes by processing the 'effects' of a switch statement.
360 void processSwitch(SwitchNodeBuilder& builder);
361
362 /// Called by CoreEngine. Used to notify checkers that processing a
363 /// function has begun. Called for both inlined and top-level functions.
364 void processBeginOfFunction(NodeBuilderContext &BC,
365 ExplodedNode *Pred, ExplodedNodeSet &Dst,
366 const BlockEdge &L);
367
368 /// Called by CoreEngine. Used to notify checkers that processing a
369 /// function has ended. Called for both inlined and top-level functions.
370 void processEndOfFunction(NodeBuilderContext& BC,
371 ExplodedNode *Pred,
372 const ReturnStmt *RS = nullptr);
373
374 /// Remove dead bindings/symbols before exiting a function.
375 void removeDeadOnEndOfFunction(NodeBuilderContext& BC,
376 ExplodedNode *Pred,
377 ExplodedNodeSet &Dst);
378
379 /// Generate the entry node of the callee.
380 void processCallEnter(NodeBuilderContext& BC, CallEnter CE,
381 ExplodedNode *Pred);
382
383 /// Generate the sequence of nodes that simulate the call exit and the post
384 /// visit for CallExpr.
385 void processCallExit(ExplodedNode *Pred);
386
387 /// Called by CoreEngine when the analysis worklist has terminated.
388 void processEndWorklist();
389
390 /// evalAssume - Callback function invoked by the ConstraintManager when
391 /// making assumptions about state values.
392 ProgramStateRef processAssume(ProgramStateRef state, SVal cond,
393 bool assumption);
394
395 /// processRegionChanges - Called by ProgramStateManager whenever a change is made
396 /// to the store. Used to update checkers that track region values.
397 ProgramStateRef
398 processRegionChanges(ProgramStateRef state,
399 const InvalidatedSymbols *invalidated,
400 ArrayRef<const MemRegion *> ExplicitRegions,
401 ArrayRef<const MemRegion *> Regions,
402 const LocationContext *LCtx,
403 const CallEvent *Call);
404
405 inline ProgramStateRef
406 processRegionChange(ProgramStateRef state,
407 const MemRegion* MR,
408 const LocationContext *LCtx) {
409 return processRegionChanges(state, nullptr, MR, MR, LCtx, nullptr);
410 }
411
412 /// printJson - Called by ProgramStateManager to print checker-specific data.
413 void printJson(raw_ostream &Out, ProgramStateRef State,
414 const LocationContext *LCtx, const char *NL,
415 unsigned int Space, bool IsDot) const;
416
417 ProgramStateManager &getStateManager() { return StateMgr; }
418
419 StoreManager &getStoreManager() { return StateMgr.getStoreManager(); }
420
421 ConstraintManager &getConstraintManager() {
422 return StateMgr.getConstraintManager();
423 }
424
425 // FIXME: Remove when we migrate over to just using SValBuilder.
426 BasicValueFactory &getBasicVals() {
427 return StateMgr.getBasicVals();
428 }
429
430 SymbolManager &getSymbolManager() { return SymMgr; }
431 MemRegionManager &getRegionManager() { return MRMgr; }
432
433 DataTag::Factory &getDataTags() { return Engine.getDataTags(); }
434
435 // Functions for external checking of whether we have unfinished work
436 bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); }
437 bool hasEmptyWorkList() const { return !Engine.getWorkList()->hasWork(); }
438 bool hasWorkRemaining() const { return Engine.hasWorkRemaining(); }
439
440 const CoreEngine &getCoreEngine() const { return Engine; }
441
442public:
443 /// Visit - Transfer function logic for all statements. Dispatches to
444 /// other functions that handle specific kinds of statements.
445 void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst);
446
447 /// VisitArrayInitLoopExpr - Transfer function for array init loop.
448 void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *Ex, ExplodedNode *Pred,
449 ExplodedNodeSet &Dst);
450
451 /// VisitArraySubscriptExpr - Transfer function for array accesses.
452 void VisitArraySubscriptExpr(const ArraySubscriptExpr *Ex,
453 ExplodedNode *Pred,
454 ExplodedNodeSet &Dst);
455
456 /// VisitGCCAsmStmt - Transfer function logic for inline asm.
457 void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
458 ExplodedNodeSet &Dst);
459
460 /// VisitMSAsmStmt - Transfer function logic for MS inline asm.
461 void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
462 ExplodedNodeSet &Dst);
463
464 /// VisitBlockExpr - Transfer function logic for BlockExprs.
465 void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
466 ExplodedNodeSet &Dst);
467
468 /// VisitLambdaExpr - Transfer function logic for LambdaExprs.
469 void VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
470 ExplodedNodeSet &Dst);
471
472 /// VisitBinaryOperator - Transfer function logic for binary operators.
473 void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode *Pred,
474 ExplodedNodeSet &Dst);
475
476
477 /// VisitCall - Transfer function for function calls.
478 void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
479 ExplodedNodeSet &Dst);
480
481 /// VisitCast - Transfer function logic for all casts (implicit and explicit).
482 void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred,
483 ExplodedNodeSet &Dst);
484
485 /// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
486 void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
487 ExplodedNode *Pred, ExplodedNodeSet &Dst);
488
489 /// Transfer function logic for DeclRefExprs and BlockDeclRefExprs.
490 void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D,
491 ExplodedNode *Pred, ExplodedNodeSet &Dst);
492
493 /// VisitDeclStmt - Transfer function logic for DeclStmts.
494 void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
495 ExplodedNodeSet &Dst);
496
497 /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
498 void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R,
499 ExplodedNode *Pred, ExplodedNodeSet &Dst);
500
501 void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred,
502 ExplodedNodeSet &Dst);
503
504 /// VisitLogicalExpr - Transfer function logic for '&&', '||'
505 void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
506 ExplodedNodeSet &Dst);
507
508 /// VisitMemberExpr - Transfer function for member expressions.
509 void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
510 ExplodedNodeSet &Dst);
511
512 /// VisitAtomicExpr - Transfer function for builtin atomic expressions
513 void VisitAtomicExpr(const AtomicExpr *E, ExplodedNode *Pred,
514 ExplodedNodeSet &Dst);
515
516 /// Transfer function logic for ObjCAtSynchronizedStmts.
517 void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
518 ExplodedNode *Pred, ExplodedNodeSet &Dst);
519
520 /// Transfer function logic for computing the lvalue of an Objective-C ivar.
521 void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *DR, ExplodedNode *Pred,
522 ExplodedNodeSet &Dst);
523
524 /// VisitObjCForCollectionStmt - Transfer function logic for
525 /// ObjCForCollectionStmt.
526 void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
527 ExplodedNode *Pred, ExplodedNodeSet &Dst);
528
529 void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred,
530 ExplodedNodeSet &Dst);
531
532 /// VisitReturnStmt - Transfer function logic for return statements.
533 void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred,
534 ExplodedNodeSet &Dst);
535
536 /// VisitOffsetOfExpr - Transfer function for offsetof.
537 void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred,
538 ExplodedNodeSet &Dst);
539
540 /// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.
541 void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
542 ExplodedNode *Pred, ExplodedNodeSet &Dst);
543
544 /// VisitUnaryOperator - Transfer function logic for unary operators.
545 void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred,
546 ExplodedNodeSet &Dst);
547
548 /// Handle ++ and -- (both pre- and post-increment).
549 void VisitIncrementDecrementOperator(const UnaryOperator* U,
550 ExplodedNode *Pred,
551 ExplodedNodeSet &Dst);
552
553 void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
554 ExplodedNodeSet &PreVisit,
555 ExplodedNodeSet &Dst);
556
557 void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred,
558 ExplodedNodeSet &Dst);
559
560 void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
561 ExplodedNodeSet & Dst);
562
563 void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred,
564 ExplodedNodeSet &Dst);
565
566 void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E,
567 ExplodedNode *Pred, ExplodedNodeSet &Dst);
568
569 void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest,
570 const Stmt *S, bool IsBaseDtor,
571 ExplodedNode *Pred, ExplodedNodeSet &Dst,
572 EvalCallOptions &Options);
573
574 void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
575 ExplodedNode *Pred,
576 ExplodedNodeSet &Dst);
577
578 void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
579 ExplodedNodeSet &Dst);
580
581 void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred,
582 ExplodedNodeSet &Dst);
583
584 /// Create a C++ temporary object for an rvalue.
585 void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
586 ExplodedNode *Pred,
587 ExplodedNodeSet &Dst);
588
589 /// evalEagerlyAssumeBinOpBifurcation - Given the nodes in 'Src', eagerly assume symbolic
590 /// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
591 /// with those assumptions.
592 void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
593 const Expr *Ex);
594
595 static std::pair<const ProgramPointTag *, const ProgramPointTag *>
596 geteagerlyAssumeBinOpBifurcationTags();
597
598 ProgramStateRef handleLValueBitCast(ProgramStateRef state, const Expr *Ex,
599 const LocationContext *LCtx, QualType T,
600 QualType ExTy, const CastExpr *CastE,
601 StmtNodeBuilder &Bldr,
602 ExplodedNode *Pred);
603
604 ProgramStateRef handleLVectorSplat(ProgramStateRef state,
605 const LocationContext *LCtx,
606 const CastExpr *CastE,
607 StmtNodeBuilder &Bldr,
608 ExplodedNode *Pred);
609
610 void handleUOExtension(ExplodedNodeSet::iterator I,
611 const UnaryOperator* U,
612 StmtNodeBuilder &Bldr);
613
614public:
615 SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op,
616 SVal LHS, SVal RHS, QualType T) {
617 return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T);
618 }
619
620 /// Retreives which element is being constructed in a non-POD type array.
621 static Optional<unsigned>
622 getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E,
623 const LocationContext *LCtx);
624
625 /// Retreives which element is being destructed in a non-POD type array.
626 static Optional<unsigned>
627 getPendingArrayDestruction(ProgramStateRef State,
628 const LocationContext *LCtx);
629
630 /// Retreives the size of the array in the pending ArrayInitLoopExpr.
631 static Optional<unsigned> getPendingInitLoop(ProgramStateRef State,
632 const CXXConstructExpr *E,
633 const LocationContext *LCtx);
634
635 /// By looking at a certain item that may be potentially part of an object's
636 /// ConstructionContext, retrieve such object's location. A particular
637 /// statement can be transparently passed as \p Item in most cases.
638 static Optional<SVal>
639 getObjectUnderConstruction(ProgramStateRef State,
640 const ConstructionContextItem &Item,
641 const LocationContext *LC);
642
643 /// Call PointerEscape callback when a value escapes as a result of bind.
644 ProgramStateRef processPointerEscapedOnBind(
645 ProgramStateRef State, ArrayRef<std::pair<SVal, SVal>> LocAndVals,
646 const LocationContext *LCtx, PointerEscapeKind Kind,
647 const CallEvent *Call);
648
649 /// Call PointerEscape callback when a value escapes as a result of
650 /// region invalidation.
651 /// \param[in] ITraits Specifies invalidation traits for regions/symbols.
652 ProgramStateRef notifyCheckersOfPointerEscape(
653 ProgramStateRef State,
654 const InvalidatedSymbols *Invalidated,
655 ArrayRef<const MemRegion *> ExplicitRegions,
656 const CallEvent *Call,
657 RegionAndSymbolInvalidationTraits &ITraits);
658
659private:
660 /// evalBind - Handle the semantics of binding a value to a specific location.
661 /// This method is used by evalStore, VisitDeclStmt, and others.
662 void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred,
663 SVal location, SVal Val, bool atDeclInit = false,
664 const ProgramPoint *PP = nullptr);
665
666 ProgramStateRef
667 processPointerEscapedOnBind(ProgramStateRef State,
668 SVal Loc, SVal Val,
669 const LocationContext *LCtx);
670
671 /// A simple wrapper when you only need to notify checkers of pointer-escape
672 /// of some values.
673 ProgramStateRef escapeValues(ProgramStateRef State, ArrayRef<SVal> Vs,
674 PointerEscapeKind K,
675 const CallEvent *Call = nullptr) const;
676
677public:
678 // FIXME: 'tag' should be removed, and a LocationContext should be used
679 // instead.
680 // FIXME: Comment on the meaning of the arguments, when 'St' may not
681 // be the same as Pred->state, and when 'location' may not be the
682 // same as state->getLValue(Ex).
683 /// Simulate a read of the result of Ex.
684 void evalLoad(ExplodedNodeSet &Dst,
685 const Expr *NodeEx, /* Eventually will be a CFGStmt */
686 const Expr *BoundExpr,
687 ExplodedNode *Pred,
688 ProgramStateRef St,
689 SVal location,
690 const ProgramPointTag *tag = nullptr,
691 QualType LoadTy = QualType());
692
693 // FIXME: 'tag' should be removed, and a LocationContext should be used
694 // instead.
695 void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE,
696 ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val,
697 const ProgramPointTag *tag = nullptr);
698
699 /// Return the CFG element corresponding to the worklist element
700 /// that is currently being processed by ExprEngine.
701 CFGElement getCurrentCFGElement() {
702 return (*currBldrCtx->getBlock())[currStmtIdx];
703 }
704
705 /// Create a new state in which the call return value is binded to the
706 /// call origin expression.
707 ProgramStateRef bindReturnValue(const CallEvent &Call,
708 const LocationContext *LCtx,
709 ProgramStateRef State);
710
711 /// Evaluate a call, running pre- and post-call checkers and allowing checkers
712 /// to be responsible for handling the evaluation of the call itself.
713 void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
714 const CallEvent &Call);
715
716 /// Default implementation of call evaluation.
717 void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred,
718 const CallEvent &Call,
719 const EvalCallOptions &CallOpts = {});
720
721 /// Find location of the object that is being constructed by a given
722 /// constructor. This should ideally always succeed but due to not being
723 /// fully implemented it sometimes indicates that it failed via its
724 /// out-parameter CallOpts; in such cases a fake temporary region is
725 /// returned, which is better than nothing but does not represent
726 /// the actual behavior of the program. The Idx parameter is used if we
727 /// construct an array of objects. In that case it points to the index
728 /// of the continuous memory region.
729 /// E.g.:
730 /// For `int arr[4]` this index can be 0,1,2,3.
731 /// For `int arr2[3][3]` this index can be 0,1,...,7,8.
732 /// A multi-dimensional array is also a continuous memory location in a
733 /// row major order, so for arr[0][0] Idx is 0 and for arr[2][2] Idx is 8.
734 SVal computeObjectUnderConstruction(const Expr *E, ProgramStateRef State,
735 const NodeBuilderContext *BldrCtx,
736 const LocationContext *LCtx,
737 const ConstructionContext *CC,
738 EvalCallOptions &CallOpts,
739 unsigned Idx = 0);
740
741 /// Update the program state with all the path-sensitive information
742 /// that's necessary to perform construction of an object with a given
743 /// syntactic construction context. V and CallOpts have to be obtained from
744 /// computeObjectUnderConstruction() invoked with the same set of
745 /// the remaining arguments (E, State, LCtx, CC).
746 ProgramStateRef updateObjectsUnderConstruction(
747 SVal V, const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
748 const ConstructionContext *CC, const EvalCallOptions &CallOpts);
749
750 /// A convenient wrapper around computeObjectUnderConstruction
751 /// and updateObjectsUnderConstruction.
752 std::pair<ProgramStateRef, SVal> handleConstructionContext(
753 const Expr *E, ProgramStateRef State, const NodeBuilderContext *BldrCtx,
754 const LocationContext *LCtx, const ConstructionContext *CC,
755 EvalCallOptions &CallOpts, unsigned Idx = 0) {
756
757 SVal V = computeObjectUnderConstruction(E, State, BldrCtx, LCtx, CC,
19
Calling 'ExprEngine::computeObjectUnderConstruction'
758 CallOpts, Idx);
759 State = updateObjectsUnderConstruction(V, E, State, LCtx, CC, CallOpts);
760
761 return std::make_pair(State, V);
762 }
763
764private:
765 ProgramStateRef finishArgumentConstruction(ProgramStateRef State,
766 const CallEvent &Call);
767 void finishArgumentConstruction(ExplodedNodeSet &Dst, ExplodedNode *Pred,
768 const CallEvent &Call);
769
770 void evalLoadCommon(ExplodedNodeSet &Dst,
771 const Expr *NodeEx, /* Eventually will be a CFGStmt */
772 const Expr *BoundEx,
773 ExplodedNode *Pred,
774 ProgramStateRef St,
775 SVal location,
776 const ProgramPointTag *tag,
777 QualType LoadTy);
778
779 void evalLocation(ExplodedNodeSet &Dst,
780 const Stmt *NodeEx, /* This will eventually be a CFGStmt */
781 const Stmt *BoundEx,
782 ExplodedNode *Pred,
783 ProgramStateRef St,
784 SVal location,
785 bool isLoad);
786
787 /// Count the stack depth and determine if the call is recursive.
788 void examineStackFrames(const Decl *D, const LocationContext *LCtx,
789 bool &IsRecursive, unsigned &StackDepth);
790
791 enum CallInlinePolicy {
792 CIP_Allowed,
793 CIP_DisallowedOnce,
794 CIP_DisallowedAlways
795 };
796
797 /// See if a particular call should be inlined, by only looking
798 /// at the call event and the current state of analysis.
799 CallInlinePolicy mayInlineCallKind(const CallEvent &Call,
800 const ExplodedNode *Pred,
801 AnalyzerOptions &Opts,
802 const EvalCallOptions &CallOpts);
803
804 /// See if the given AnalysisDeclContext is built for a function that we
805 /// should always inline simply because it's small enough.
806 /// Apart from "small" functions, we also have "large" functions
807 /// (cf. isLarge()), some of which are huge (cf. isHuge()), and we classify
808 /// the remaining functions as "medium".
809 bool isSmall(AnalysisDeclContext *ADC) const;
810
811 /// See if the given AnalysisDeclContext is built for a function that we
812 /// should inline carefully because it looks pretty large.
813 bool isLarge(AnalysisDeclContext *ADC) const;
814
815 /// See if the given AnalysisDeclContext is built for a function that we
816 /// should never inline because it's legit gigantic.
817 bool isHuge(AnalysisDeclContext *ADC) const;
818
819 /// See if the given AnalysisDeclContext is built for a function that we
820 /// should inline, just by looking at the declaration of the function.
821 bool mayInlineDecl(AnalysisDeclContext *ADC) const;
822
823 /// Checks our policies and decides weither the given call should be inlined.
824 bool shouldInlineCall(const CallEvent &Call, const Decl *D,
825 const ExplodedNode *Pred,
826 const EvalCallOptions &CallOpts = {});
827
828 /// Checks whether our policies allow us to inline a non-POD type array
829 /// construction.
830 bool shouldInlineArrayConstruction(const ProgramStateRef State,
831 const CXXConstructExpr *CE,
832 const LocationContext *LCtx);
833
834 /// Checks whether our policies allow us to inline a non-POD type array
835 /// destruction.
836 /// \param Size The size of the array.
837 bool shouldInlineArrayDestruction(uint64_t Size);
838
839 /// Prepares the program state for array destruction. If no error happens
840 /// the function binds a 'PendingArrayDestruction' entry to the state, which
841 /// it returns along with the index. If any error happens (we fail to read
842 /// the size, the index would be -1, etc.) the function will return the
843 /// original state along with an index of 0. The actual element count of the
844 /// array can be accessed by the optional 'ElementCountVal' parameter. \param
845 /// State The program state. \param Region The memory region where the array
846 /// is stored. \param ElementTy The type an element in the array. \param LCty
847 /// The location context. \param ElementCountVal A pointer to an optional
848 /// SVal. If specified, the size of the array will be returned in it. It can
849 /// be Unknown.
850 std::pair<ProgramStateRef, uint64_t> prepareStateForArrayDestruction(
851 const ProgramStateRef State, const MemRegion *Region,
852 const QualType &ElementTy, const LocationContext *LCtx,
853 SVal *ElementCountVal = nullptr);
854
855 /// Checks whether we construct an array of non-POD type, and decides if the
856 /// constructor should be inkoved once again.
857 bool shouldRepeatCtorCall(ProgramStateRef State, const CXXConstructExpr *E,
858 const LocationContext *LCtx);
859
860 void inlineCall(WorkList *WList, const CallEvent &Call, const Decl *D,
861 NodeBuilder &Bldr, ExplodedNode *Pred, ProgramStateRef State);
862
863 void ctuBifurcate(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
864 ExplodedNode *Pred, ProgramStateRef State);
865
866 /// Returns true if the CTU analysis is running its second phase.
867 bool isSecondPhaseCTU() { return IsCTUEnabled && !Engine.getCTUWorkList(); }
868
869 /// Conservatively evaluate call by invalidating regions and binding
870 /// a conjured return value.
871 void conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr,
872 ExplodedNode *Pred, ProgramStateRef State);
873
874 /// Either inline or process the call conservatively (or both), based
875 /// on DynamicDispatchBifurcation data.
876 void BifurcateCall(const MemRegion *BifurReg,
877 const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
878 ExplodedNode *Pred);
879
880 bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC);
881
882 /// Models a trivial copy or move constructor or trivial assignment operator
883 /// call with a simple bind.
884 void performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
885 const CallEvent &Call);
886
887 /// If the value of the given expression \p InitWithAdjustments is a NonLoc,
888 /// copy it into a new temporary object region, and replace the value of the
889 /// expression with that.
890 ///
891 /// If \p Result is provided, the new region will be bound to this expression
892 /// instead of \p InitWithAdjustments.
893 ///
894 /// Returns the temporary region with adjustments into the optional
895 /// OutRegionWithAdjustments out-parameter if a new region was indeed needed,
896 /// otherwise sets it to nullptr.
897 ProgramStateRef createTemporaryRegionIfNeeded(
898 ProgramStateRef State, const LocationContext *LC,
899 const Expr *InitWithAdjustments, const Expr *Result = nullptr,
900 const SubRegion **OutRegionWithAdjustments = nullptr);
901
902 /// Returns a region representing the `Idx`th element of a (possibly
903 /// multi-dimensional) array, for the purposes of element construction or
904 /// destruction.
905 ///
906 /// On return, \p Ty will be set to the base type of the array.
907 ///
908 /// If the type is not an array type at all, the original value is returned.
909 /// Otherwise the "IsArray" flag is set.
910 static SVal makeElementRegion(ProgramStateRef State, SVal LValue,
911 QualType &Ty, bool &IsArray, unsigned Idx = 0);
912
913 /// For a DeclStmt or CXXInitCtorInitializer, walk backward in the current CFG
914 /// block to find the constructor expression that directly constructed into
915 /// the storage for this statement. Returns null if the constructor for this
916 /// statement created a temporary object region rather than directly
917 /// constructing into an existing region.
918 const CXXConstructExpr *findDirectConstructorForCurrentCFGElement();
919
920 /// Common code that handles either a CXXConstructExpr or a
921 /// CXXInheritedCtorInitExpr.
922 void handleConstructor(const Expr *E, ExplodedNode *Pred,
923 ExplodedNodeSet &Dst);
924
925public:
926 /// Note whether this loop has any more iteratios to model. These methods are
927 /// essentially an interface for a GDM trait. Further reading in
928 /// ExprEngine::VisitObjCForCollectionStmt().
929 [[nodiscard]] static ProgramStateRef
930 setWhetherHasMoreIteration(ProgramStateRef State,
931 const ObjCForCollectionStmt *O,
932 const LocationContext *LC, bool HasMoreIteraton);
933
934 [[nodiscard]] static ProgramStateRef
935 removeIterationState(ProgramStateRef State, const ObjCForCollectionStmt *O,
936 const LocationContext *LC);
937
938 [[nodiscard]] static bool hasMoreIteration(ProgramStateRef State,
939 const ObjCForCollectionStmt *O,
940 const LocationContext *LC);
941
942private:
943 /// Assuming we construct an array of non-POD types, this method allows us
944 /// to store which element is to be constructed next.
945 static ProgramStateRef
946 setIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E,
947 const LocationContext *LCtx, unsigned Idx);
948
949 static ProgramStateRef
950 removeIndexOfElementToConstruct(ProgramStateRef State,
951 const CXXConstructExpr *E,
952 const LocationContext *LCtx);
953
954 /// Assuming we destruct an array of non-POD types, this method allows us
955 /// to store which element is to be destructed next.
956 static ProgramStateRef setPendingArrayDestruction(ProgramStateRef State,
957 const LocationContext *LCtx,
958 unsigned Idx);
959
960 static ProgramStateRef
961 removePendingArrayDestruction(ProgramStateRef State,
962 const LocationContext *LCtx);
963
964 /// Sets the size of the array in a pending ArrayInitLoopExpr.
965 static ProgramStateRef setPendingInitLoop(ProgramStateRef State,
966 const CXXConstructExpr *E,
967 const LocationContext *LCtx,
968 unsigned Idx);
969
970 static ProgramStateRef removePendingInitLoop(ProgramStateRef State,
971 const CXXConstructExpr *E,
972 const LocationContext *LCtx);
973
974 static ProgramStateRef
975 removeStateTraitsUsedForArrayEvaluation(ProgramStateRef State,
976 const CXXConstructExpr *E,
977 const LocationContext *LCtx);
978
979 /// Store the location of a C++ object corresponding to a statement
980 /// until the statement is actually encountered. For example, if a DeclStmt
981 /// has CXXConstructExpr as its initializer, the object would be considered
982 /// to be "under construction" between CXXConstructExpr and DeclStmt.
983 /// This allows, among other things, to keep bindings to variable's fields
984 /// made within the constructor alive until its declaration actually
985 /// goes into scope.
986 static ProgramStateRef
987 addObjectUnderConstruction(ProgramStateRef State,
988 const ConstructionContextItem &Item,
989 const LocationContext *LC, SVal V);
990
991 /// Mark the object sa fully constructed, cleaning up the state trait
992 /// that tracks objects under construction.
993 static ProgramStateRef
994 finishObjectConstruction(ProgramStateRef State,
995 const ConstructionContextItem &Item,
996 const LocationContext *LC);
997
998 /// If the given expression corresponds to a temporary that was used for
999 /// passing into an elidable copy/move constructor and that constructor
1000 /// was actually elided, track that we also need to elide the destructor.
1001 static ProgramStateRef elideDestructor(ProgramStateRef State,
1002 const CXXBindTemporaryExpr *BTE,
1003 const LocationContext *LC);
1004
1005 /// Stop tracking the destructor that corresponds to an elided constructor.
1006 static ProgramStateRef
1007 cleanupElidedDestructor(ProgramStateRef State,
1008 const CXXBindTemporaryExpr *BTE,
1009 const LocationContext *LC);
1010
1011 /// Returns true if the given expression corresponds to a temporary that
1012 /// was constructed for passing into an elidable copy/move constructor
1013 /// and that constructor was actually elided.
1014 static bool isDestructorElided(ProgramStateRef State,
1015 const CXXBindTemporaryExpr *BTE,
1016 const LocationContext *LC);
1017
1018 /// Check if all objects under construction have been fully constructed
1019 /// for the given context range (including FromLC, not including ToLC).
1020 /// This is useful for assertions. Also checks if elided destructors
1021 /// were cleaned up.
1022 static bool areAllObjectsFullyConstructed(ProgramStateRef State,
1023 const LocationContext *FromLC,
1024 const LocationContext *ToLC);
1025};
1026
1027/// Traits for storing the call processing policy inside GDM.
1028/// The GDM stores the corresponding CallExpr pointer.
1029// FIXME: This does not use the nice trait macros because it must be accessible
1030// from multiple translation units.
1031struct ReplayWithoutInlining{};
1032template <>
1033struct ProgramStateTrait<ReplayWithoutInlining> :
1034 public ProgramStatePartialTrait<const void*> {
1035 static void *GDMIndex();
1036};
1037
1038} // namespace ento
1039
1040} // namespace clang
1041
1042#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H