Bug Summary

File:build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
Warning:line 305, 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/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/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/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/clang/lib/StaticAnalyzer/Core -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/clang/include -I tools/clang/include -I include -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/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/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm=build-llvm -fmacro-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm=build-llvm -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -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/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm=build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -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-09-04-125545-48738-1 -x c++ /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

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

/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/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 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 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 LocationContext *LCtx,
736 const ConstructionContext *CC,
737 EvalCallOptions &CallOpts,
738 unsigned Idx = 0);
739
740 /// Update the program state with all the path-sensitive information
741 /// that's necessary to perform construction of an object with a given
742 /// syntactic construction context. V and CallOpts have to be obtained from
743 /// computeObjectUnderConstruction() invoked with the same set of
744 /// the remaining arguments (E, State, LCtx, CC).
745 ProgramStateRef updateObjectsUnderConstruction(
746 SVal V, const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
747 const ConstructionContext *CC, const EvalCallOptions &CallOpts);
748
749 /// A convenient wrapper around computeObjectUnderConstruction
750 /// and updateObjectsUnderConstruction.
751 std::pair<ProgramStateRef, SVal>
752 handleConstructionContext(const Expr *E, ProgramStateRef State,
753 const LocationContext *LCtx,
754 const ConstructionContext *CC,
755 EvalCallOptions &CallOpts, unsigned Idx = 0) {
756
757 SVal V = computeObjectUnderConstruction(E, State, LCtx, CC, CallOpts, Idx);
19
Calling 'ExprEngine::computeObjectUnderConstruction'
758 State = updateObjectsUnderConstruction(V, E, State, LCtx, CC, CallOpts);
759
760 return std::make_pair(State, V);
761 }
762
763private:
764 ProgramStateRef finishArgumentConstruction(ProgramStateRef State,
765 const CallEvent &Call);
766 void finishArgumentConstruction(ExplodedNodeSet &Dst, ExplodedNode *Pred,
767 const CallEvent &Call);
768
769 void evalLoadCommon(ExplodedNodeSet &Dst,
770 const Expr *NodeEx, /* Eventually will be a CFGStmt */
771 const Expr *BoundEx,
772 ExplodedNode *Pred,
773 ProgramStateRef St,
774 SVal location,
775 const ProgramPointTag *tag,
776 QualType LoadTy);
777
778 void evalLocation(ExplodedNodeSet &Dst,
779 const Stmt *NodeEx, /* This will eventually be a CFGStmt */
780 const Stmt *BoundEx,
781 ExplodedNode *Pred,
782 ProgramStateRef St,
783 SVal location,
784 bool isLoad);
785
786 /// Count the stack depth and determine if the call is recursive.
787 void examineStackFrames(const Decl *D, const LocationContext *LCtx,
788 bool &IsRecursive, unsigned &StackDepth);
789
790 enum CallInlinePolicy {
791 CIP_Allowed,
792 CIP_DisallowedOnce,
793 CIP_DisallowedAlways
794 };
795
796 /// See if a particular call should be inlined, by only looking
797 /// at the call event and the current state of analysis.
798 CallInlinePolicy mayInlineCallKind(const CallEvent &Call,
799 const ExplodedNode *Pred,
800 AnalyzerOptions &Opts,
801 const EvalCallOptions &CallOpts);
802
803 /// See if the given AnalysisDeclContext is built for a function that we
804 /// should always inline simply because it's small enough.
805 /// Apart from "small" functions, we also have "large" functions
806 /// (cf. isLarge()), some of which are huge (cf. isHuge()), and we classify
807 /// the remaining functions as "medium".
808 bool isSmall(AnalysisDeclContext *ADC) const;
809
810 /// See if the given AnalysisDeclContext is built for a function that we
811 /// should inline carefully because it looks pretty large.
812 bool isLarge(AnalysisDeclContext *ADC) const;
813
814 /// See if the given AnalysisDeclContext is built for a function that we
815 /// should never inline because it's legit gigantic.
816 bool isHuge(AnalysisDeclContext *ADC) const;
817
818 /// See if the given AnalysisDeclContext is built for a function that we
819 /// should inline, just by looking at the declaration of the function.
820 bool mayInlineDecl(AnalysisDeclContext *ADC) const;
821
822 /// Checks our policies and decides weither the given call should be inlined.
823 bool shouldInlineCall(const CallEvent &Call, const Decl *D,
824 const ExplodedNode *Pred,
825 const EvalCallOptions &CallOpts = {});
826
827 /// Checks whether our policies allow us to inline a non-POD type array
828 /// construction.
829 bool shouldInlineArrayConstruction(const ProgramStateRef State,
830 const CXXConstructExpr *CE,
831 const LocationContext *LCtx);
832
833 /// Checks whether our policies allow us to inline a non-POD type array
834 /// destruction.
835 /// \param Size The size of the array.
836 bool shouldInlineArrayDestruction(uint64_t Size);
837
838 /// Prepares the program state for array destruction. If no error happens
839 /// the function binds a 'PendingArrayDestruction' entry to the state, which
840 /// it returns along with the index. If any error happens (we fail to read
841 /// the size, the index would be -1, etc.) the function will return the
842 /// original state along with an index of 0. The actual element count of the
843 /// array can be accessed by the optional 'ElementCountVal' parameter. \param
844 /// State The program state. \param Region The memory region where the array
845 /// is stored. \param ElementTy The type an element in the array. \param LCty
846 /// The location context. \param ElementCountVal A pointer to an optional
847 /// SVal. If specified, the size of the array will be returned in it. It can
848 /// be Unknown.
849 std::pair<ProgramStateRef, uint64_t> prepareStateForArrayDestruction(
850 const ProgramStateRef State, const MemRegion *Region,
851 const QualType &ElementTy, const LocationContext *LCtx,
852 SVal *ElementCountVal = nullptr);
853
854 /// Checks whether we construct an array of non-POD type, and decides if the
855 /// constructor should be inkoved once again.
856 bool shouldRepeatCtorCall(ProgramStateRef State, const CXXConstructExpr *E,
857 const LocationContext *LCtx);
858
859 void inlineCall(WorkList *WList, const CallEvent &Call, const Decl *D,
860 NodeBuilder &Bldr, ExplodedNode *Pred, ProgramStateRef State);
861
862 void ctuBifurcate(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
863 ExplodedNode *Pred, ProgramStateRef State);
864
865 /// Returns true if the CTU analysis is running its second phase.
866 bool isSecondPhaseCTU() { return IsCTUEnabled && !Engine.getCTUWorkList(); }
867
868 /// Conservatively evaluate call by invalidating regions and binding
869 /// a conjured return value.
870 void conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr,
871 ExplodedNode *Pred, ProgramStateRef State);
872
873 /// Either inline or process the call conservatively (or both), based
874 /// on DynamicDispatchBifurcation data.
875 void BifurcateCall(const MemRegion *BifurReg,
876 const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
877 ExplodedNode *Pred);
878
879 bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC);
880
881 /// Models a trivial copy or move constructor or trivial assignment operator
882 /// call with a simple bind.
883 void performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
884 const CallEvent &Call);
885
886 /// If the value of the given expression \p InitWithAdjustments is a NonLoc,
887 /// copy it into a new temporary object region, and replace the value of the
888 /// expression with that.
889 ///
890 /// If \p Result is provided, the new region will be bound to this expression
891 /// instead of \p InitWithAdjustments.
892 ///
893 /// Returns the temporary region with adjustments into the optional
894 /// OutRegionWithAdjustments out-parameter if a new region was indeed needed,
895 /// otherwise sets it to nullptr.
896 ProgramStateRef createTemporaryRegionIfNeeded(
897 ProgramStateRef State, const LocationContext *LC,
898 const Expr *InitWithAdjustments, const Expr *Result = nullptr,
899 const SubRegion **OutRegionWithAdjustments = nullptr);
900
901 /// Returns a region representing the `Idx`th element of a (possibly
902 /// multi-dimensional) array, for the purposes of element construction or
903 /// destruction.
904 ///
905 /// On return, \p Ty will be set to the base type of the array.
906 ///
907 /// If the type is not an array type at all, the original value is returned.
908 /// Otherwise the "IsArray" flag is set.
909 static SVal makeElementRegion(ProgramStateRef State, SVal LValue,
910 QualType &Ty, bool &IsArray, unsigned Idx = 0);
911
912 /// For a DeclStmt or CXXInitCtorInitializer, walk backward in the current CFG
913 /// block to find the constructor expression that directly constructed into
914 /// the storage for this statement. Returns null if the constructor for this
915 /// statement created a temporary object region rather than directly
916 /// constructing into an existing region.
917 const CXXConstructExpr *findDirectConstructorForCurrentCFGElement();
918
919 /// Common code that handles either a CXXConstructExpr or a
920 /// CXXInheritedCtorInitExpr.
921 void handleConstructor(const Expr *E, ExplodedNode *Pred,
922 ExplodedNodeSet &Dst);
923
924public:
925 /// Note whether this loop has any more iteratios to model. These methods are
926 /// essentially an interface for a GDM trait. Further reading in
927 /// ExprEngine::VisitObjCForCollectionStmt().
928 [[nodiscard]] static ProgramStateRef
929 setWhetherHasMoreIteration(ProgramStateRef State,
930 const ObjCForCollectionStmt *O,
931 const LocationContext *LC, bool HasMoreIteraton);
932
933 [[nodiscard]] static ProgramStateRef
934 removeIterationState(ProgramStateRef State, const ObjCForCollectionStmt *O,
935 const LocationContext *LC);
936
937 [[nodiscard]] static bool hasMoreIteration(ProgramStateRef State,
938 const ObjCForCollectionStmt *O,
939 const LocationContext *LC);
940
941private:
942 /// Assuming we construct an array of non-POD types, this method allows us
943 /// to store which element is to be constructed next.
944 static ProgramStateRef
945 setIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E,
946 const LocationContext *LCtx, unsigned Idx);
947
948 static ProgramStateRef
949 removeIndexOfElementToConstruct(ProgramStateRef State,
950 const CXXConstructExpr *E,
951 const LocationContext *LCtx);
952
953 /// Assuming we destruct an array of non-POD types, this method allows us
954 /// to store which element is to be destructed next.
955 static ProgramStateRef setPendingArrayDestruction(ProgramStateRef State,
956 const LocationContext *LCtx,
957 unsigned Idx);
958
959 static ProgramStateRef
960 removePendingArrayDestruction(ProgramStateRef State,
961 const LocationContext *LCtx);
962
963 /// Sets the size of the array in a pending ArrayInitLoopExpr.
964 static ProgramStateRef setPendingInitLoop(ProgramStateRef State,
965 const CXXConstructExpr *E,
966 const LocationContext *LCtx,
967 unsigned Idx);
968
969 static ProgramStateRef removePendingInitLoop(ProgramStateRef State,
970 const CXXConstructExpr *E,
971 const LocationContext *LCtx);
972
973 /// Store the location of a C++ object corresponding to a statement
974 /// until the statement is actually encountered. For example, if a DeclStmt
975 /// has CXXConstructExpr as its initializer, the object would be considered
976 /// to be "under construction" between CXXConstructExpr and DeclStmt.
977 /// This allows, among other things, to keep bindings to variable's fields
978 /// made within the constructor alive until its declaration actually
979 /// goes into scope.
980 static ProgramStateRef
981 addObjectUnderConstruction(ProgramStateRef State,
982 const ConstructionContextItem &Item,
983 const LocationContext *LC, SVal V);
984
985 /// Mark the object sa fully constructed, cleaning up the state trait
986 /// that tracks objects under construction.
987 static ProgramStateRef
988 finishObjectConstruction(ProgramStateRef State,
989 const ConstructionContextItem &Item,
990 const LocationContext *LC);
991
992 /// If the given expression corresponds to a temporary that was used for
993 /// passing into an elidable copy/move constructor and that constructor
994 /// was actually elided, track that we also need to elide the destructor.
995 static ProgramStateRef elideDestructor(ProgramStateRef State,
996 const CXXBindTemporaryExpr *BTE,
997 const LocationContext *LC);
998
999 /// Stop tracking the destructor that corresponds to an elided constructor.
1000 static ProgramStateRef
1001 cleanupElidedDestructor(ProgramStateRef State,
1002 const CXXBindTemporaryExpr *BTE,
1003 const LocationContext *LC);
1004
1005 /// Returns true if the given expression corresponds to a temporary that
1006 /// was constructed for passing into an elidable copy/move constructor
1007 /// and that constructor was actually elided.
1008 static bool isDestructorElided(ProgramStateRef State,
1009 const CXXBindTemporaryExpr *BTE,
1010 const LocationContext *LC);
1011
1012 /// Check if all objects under construction have been fully constructed
1013 /// for the given context range (including FromLC, not including ToLC).
1014 /// This is useful for assertions. Also checks if elided destructors
1015 /// were cleaned up.
1016 static bool areAllObjectsFullyConstructed(ProgramStateRef State,
1017 const LocationContext *FromLC,
1018 const LocationContext *ToLC);
1019};
1020
1021/// Traits for storing the call processing policy inside GDM.
1022/// The GDM stores the corresponding CallExpr pointer.
1023// FIXME: This does not use the nice trait macros because it must be accessible
1024// from multiple translation units.
1025struct ReplayWithoutInlining{};
1026template <>
1027struct ProgramStateTrait<ReplayWithoutInlining> :
1028 public ProgramStatePartialTrait<const void*> {
1029 static void *GDMIndex();
1030};
1031
1032} // namespace ento
1033
1034} // namespace clang
1035
1036#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H