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 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |||||
23 | using namespace clang; | ||||
24 | using namespace ento; | ||||
25 | |||||
26 | void 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. | ||||
40 | void 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 | |||||
97 | SVal 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 | |||||
114 | SVal 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
| ||||
123 | switch (CC->getKind()) { | ||||
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__)); | ||||
241 | const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC); | ||||
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( | ||||
254 | TCC->getConstructorAfterElision(), State, LCtx, | ||||
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); | ||||
298 | |||||
299 | SVal Base = loc::MemRegionVal( | ||||
300 | MRMgr.getCXXTempObjectRegion(LCC->getInitializer(), LCtx)); | ||||
301 | |||||
302 | const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E); | ||||
303 | if (getIndexOfElementToConstruct(State, CE, LCtx)) { | ||||
304 | CallOpts.IsArrayCtorOrDtor = true; | ||||
305 | Base = State->getLValue(E->getType(), svalBuilder.makeArrayIndex(Idx), | ||||
| |||||
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 | |||||
380 | ProgramStateRef 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 | |||||
494 | static ProgramStateRef | ||||
495 | bindRequiredArrayElementToEnvironment(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 | |||||
563 | void ExprEngine::handleConstructor(const Expr *E, | ||||
564 | ExplodedNode *Pred, | ||||
565 | ExplodedNodeSet &destNodes) { | ||||
566 | const auto *CE = dyn_cast<CXXConstructExpr>(E); | ||||
| |||||
567 | const auto *CIE = dyn_cast<CXXInheritedCtorInitExpr>(E); | ||||
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__)); | ||||
569 | |||||
570 | const LocationContext *LCtx = Pred->getLocationContext(); | ||||
571 | ProgramStateRef State = Pred->getState(); | ||||
572 | |||||
573 | SVal Target = UnknownVal(); | ||||
574 | |||||
575 | if (CE
| ||||
576 | if (Optional<SVal> ElidedTarget = | ||||
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__)); | ||||
594 | const ConstructionContext *CC = C ? C->getConstructionContext() : nullptr; | ||||
595 | |||||
596 | const CXXConstructExpr::ConstructionKind CK = | ||||
597 | CE
| ||||
598 | switch (CK) { | ||||
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__)); | ||||
602 | |||||
603 | // If the ctor is part of an ArrayInitLoopExpr, we want to handle it | ||||
604 | // differently. | ||||
605 | auto *AILE = CC ? CC->getArrayInitLoop() : nullptr; | ||||
606 | |||||
607 | unsigned Idx = 0; | ||||
608 | if (CE->getType()->isArrayType() || AILE) { | ||||
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
| ||||
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); | ||||
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 | |||||
828 | void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, | ||||
829 | ExplodedNode *Pred, | ||||
830 | ExplodedNodeSet &Dst) { | ||||
831 | handleConstructor(CE, Pred, Dst); | ||||
832 | } | ||||
833 | |||||
834 | void ExprEngine::VisitCXXInheritedCtorInitExpr( | ||||
835 | const CXXInheritedCtorInitExpr *CE, ExplodedNode *Pred, | ||||
836 | ExplodedNodeSet &Dst) { | ||||
837 | handleConstructor(CE, Pred, Dst); | ||||
838 | } | ||||
839 | |||||
840 | void 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 | |||||
907 | void 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 | |||||
974 | void 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 | |||||
1106 | void 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 | |||||
1128 | void 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 | |||||
1146 | void 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 | |||||
1162 | void 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 | } |
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 | |
41 | namespace clang { |
42 | |
43 | class AnalysisDeclContextManager; |
44 | class AnalyzerOptions; |
45 | class ASTContext; |
46 | class CFGBlock; |
47 | class CFGElement; |
48 | class ConstructionContext; |
49 | class CXXBindTemporaryExpr; |
50 | class CXXCatchStmt; |
51 | class CXXConstructExpr; |
52 | class CXXDeleteExpr; |
53 | class CXXNewExpr; |
54 | class CXXThisExpr; |
55 | class Decl; |
56 | class DeclStmt; |
57 | class GCCAsmStmt; |
58 | class LambdaExpr; |
59 | class LocationContext; |
60 | class MaterializeTemporaryExpr; |
61 | class MSAsmStmt; |
62 | class NamedDecl; |
63 | class ObjCAtSynchronizedStmt; |
64 | class ObjCForCollectionStmt; |
65 | class ObjCIvarRefExpr; |
66 | class ObjCMessageExpr; |
67 | class ReturnStmt; |
68 | class Stmt; |
69 | |
70 | namespace cross_tu { |
71 | |
72 | class CrossTranslationUnitContext; |
73 | |
74 | } // namespace cross_tu |
75 | |
76 | namespace ento { |
77 | |
78 | class AnalysisManager; |
79 | class BasicValueFactory; |
80 | class CallEvent; |
81 | class CheckerManager; |
82 | class ConstraintManager; |
83 | class ExplodedNodeSet; |
84 | class ExplodedNode; |
85 | class IndirectGotoNodeBuilder; |
86 | class MemRegion; |
87 | struct NodeBuilderContext; |
88 | class NodeBuilderWithSinks; |
89 | class ProgramState; |
90 | class ProgramStateManager; |
91 | class RegionAndSymbolInvalidationTraits; |
92 | class SymbolManager; |
93 | class SwitchNodeBuilder; |
94 | |
95 | /// Hints for figuring out of a call should be inlined during evalCall(). |
96 | struct 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 | |
123 | class ExprEngine { |
124 | void anchor(); |
125 | |
126 | public: |
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 | |
136 | private: |
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 | |
180 | public: |
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 | |
442 | public: |
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 | |
614 | public: |
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 | |
659 | private: |
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 | |
677 | public: |
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); |
758 | State = updateObjectsUnderConstruction(V, E, State, LCtx, CC, CallOpts); |
759 | |
760 | return std::make_pair(State, V); |
761 | } |
762 | |
763 | private: |
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 | |
924 | public: |
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 | |
941 | private: |
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. |
1025 | struct ReplayWithoutInlining{}; |
1026 | template <> |
1027 | struct 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 |