Bug Summary

File:build/source/clang/lib/Analysis/AnalysisDeclContext.cpp
Warning:line 145, column 52
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name AnalysisDeclContext.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm -resource-dir /usr/lib/llvm-17/lib/clang/17 -I tools/clang/lib/Analysis -I /build/source/clang/lib/Analysis -I /build/source/clang/include -I tools/clang/include -I include -I /build/source/llvm/include -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm=build-llvm -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm=build-llvm -fcoverage-prefix-map=/build/source/= -O3 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm -fdebug-prefix-map=/build/source/build-llvm=build-llvm -fdebug-prefix-map=/build/source/= -fdebug-prefix-map=/build/source/build-llvm=build-llvm -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2023-05-10-133810-16478-1 -x c++ /build/source/clang/lib/Analysis/AnalysisDeclContext.cpp
1//===- AnalysisDeclContext.cpp - Analysis context for Path Sens analysis --===//
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 AnalysisDeclContext, a class that manages the analysis
10// context data for path sensitive analysis.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Analysis/AnalysisDeclContext.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclBase.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/DeclObjC.h"
20#include "clang/AST/DeclTemplate.h"
21#include "clang/AST/Expr.h"
22#include "clang/AST/LambdaCapture.h"
23#include "clang/AST/ParentMap.h"
24#include "clang/AST/PrettyPrinter.h"
25#include "clang/AST/Stmt.h"
26#include "clang/AST/StmtCXX.h"
27#include "clang/AST/StmtVisitor.h"
28#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
29#include "clang/Analysis/BodyFarm.h"
30#include "clang/Analysis/CFG.h"
31#include "clang/Analysis/CFGStmtMap.h"
32#include "clang/Analysis/Support/BumpVector.h"
33#include "clang/Basic/JsonSupport.h"
34#include "clang/Basic/LLVM.h"
35#include "clang/Basic/SourceLocation.h"
36#include "clang/Basic/SourceManager.h"
37#include "llvm/ADT/DenseMap.h"
38#include "llvm/ADT/FoldingSet.h"
39#include "llvm/ADT/STLExtras.h"
40#include "llvm/ADT/SmallPtrSet.h"
41#include "llvm/ADT/iterator_range.h"
42#include "llvm/Support/Allocator.h"
43#include "llvm/Support/Casting.h"
44#include "llvm/Support/Compiler.h"
45#include "llvm/Support/ErrorHandling.h"
46#include "llvm/Support/SaveAndRestore.h"
47#include "llvm/Support/raw_ostream.h"
48#include <cassert>
49#include <memory>
50
51using namespace clang;
52
53using ManagedAnalysisMap = llvm::DenseMap<const void *, std::unique_ptr<ManagedAnalysis>>;
54
55AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *ADCMgr,
56 const Decl *D,
57 const CFG::BuildOptions &Options)
58 : ADCMgr(ADCMgr), D(D), cfgBuildOptions(Options) {
59 cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
60}
61
62AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *ADCMgr,
63 const Decl *D)
64 : ADCMgr(ADCMgr), D(D) {
65 cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
66}
67
68AnalysisDeclContextManager::AnalysisDeclContextManager(
69 ASTContext &ASTCtx, bool useUnoptimizedCFG, bool addImplicitDtors,
70 bool addInitializers, bool addTemporaryDtors, bool addLifetime,
71 bool addLoopExit, bool addScopes, bool synthesizeBodies,
72 bool addStaticInitBranch, bool addCXXNewAllocator,
73 bool addRichCXXConstructors, bool markElidedCXXConstructors,
74 bool addVirtualBaseBranches, CodeInjector *injector)
75 : Injector(injector), FunctionBodyFarm(ASTCtx, injector),
76 SynthesizeBodies(synthesizeBodies) {
77 cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG;
78 cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
79 cfgBuildOptions.AddInitializers = addInitializers;
80 cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
81 cfgBuildOptions.AddLifetime = addLifetime;
82 cfgBuildOptions.AddLoopExit = addLoopExit;
83 cfgBuildOptions.AddScopes = addScopes;
84 cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
85 cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
86 cfgBuildOptions.AddRichCXXConstructors = addRichCXXConstructors;
87 cfgBuildOptions.MarkElidedCXXConstructors = markElidedCXXConstructors;
88 cfgBuildOptions.AddVirtualBaseBranches = addVirtualBaseBranches;
89}
90
91void AnalysisDeclContextManager::clear() { Contexts.clear(); }
92
93Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
94 IsAutosynthesized = false;
95 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
96 Stmt *Body = FD->getBody();
97 if (auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body))
98 Body = CoroBody->getBody();
99 if (ADCMgr && ADCMgr->synthesizeBodies()) {
100 Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(FD);
101 if (SynthesizedBody) {
102 Body = SynthesizedBody;
103 IsAutosynthesized = true;
104 }
105 }
106 return Body;
107 }
108 else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
109 Stmt *Body = MD->getBody();
110 if (ADCMgr && ADCMgr->synthesizeBodies()) {
111 Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(MD);
112 if (SynthesizedBody) {
113 Body = SynthesizedBody;
114 IsAutosynthesized = true;
115 }
116 }
117 return Body;
118 } else if (const auto *BD = dyn_cast<BlockDecl>(D))
119 return BD->getBody();
120 else if (const auto *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
121 return FunTmpl->getTemplatedDecl()->getBody();
122
123 llvm_unreachable("unknown code decl")::llvm::llvm_unreachable_internal("unknown code decl", "clang/lib/Analysis/AnalysisDeclContext.cpp"
, 123)
;
124}
125
126Stmt *AnalysisDeclContext::getBody() const {
127 bool Tmp;
128 return getBody(Tmp);
129}
130
131bool AnalysisDeclContext::isBodyAutosynthesized() const {
132 bool Tmp;
133 getBody(Tmp);
134 return Tmp;
135}
136
137bool AnalysisDeclContext::isBodyAutosynthesizedFromModelFile() const {
138 bool Tmp;
139 Stmt *Body = getBody(Tmp);
140 return Tmp && Body->getBeginLoc().isValid();
141}
142
143/// Returns true if \param VD is an Objective-C implicit 'self' parameter.
144static bool isSelfDecl(const VarDecl *VD) {
145 return isa_and_nonnull<ImplicitParamDecl>(VD) && VD->getName() == "self";
14
Assuming 'VD' is a 'class clang::ImplicitParamDecl &'
15
Called C++ object pointer is null
146}
147
148const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
149 if (const auto *MD
1.1
'MD' is null
= dyn_cast<ObjCMethodDecl>(D))
1
Assuming field 'D' is not a 'CastReturnType'
2
Taking false branch
150 return MD->getSelfDecl();
151 if (const auto *BD
3.1
'BD' is null
= dyn_cast<BlockDecl>(D)) {
3
Assuming field 'D' is not a 'CastReturnType'
4
Taking false branch
152 // See if 'self' was captured by the block.
153 for (const auto &I : BD->captures()) {
154 const VarDecl *VD = I.getVariable();
155 if (isSelfDecl(VD))
156 return dyn_cast<ImplicitParamDecl>(VD);
157 }
158 }
159
160 auto *CXXMethod = dyn_cast<CXXMethodDecl>(D);
5
Assuming field 'D' is a 'CastReturnType'
161 if (!CXXMethod
5.1
'CXXMethod' is non-null
)
6
Taking false branch
162 return nullptr;
163
164 const CXXRecordDecl *parent = CXXMethod->getParent();
165 if (!parent->isLambda())
7
Assuming the condition is false
8
Taking false branch
166 return nullptr;
167
168 for (const auto &LC : parent->captures()) {
9
Assuming '__begin1' is not equal to '__end1'
169 if (!LC.capturesVariable())
10
Taking false branch
170 continue;
171
172 ValueDecl *VD = LC.getCapturedVar();
173 if (isSelfDecl(dyn_cast<VarDecl>(VD)))
11
Assuming 'VD' is not a 'CastReturnType'
12
Passing null pointer value via 1st parameter 'VD'
13
Calling 'isSelfDecl'
174 return dyn_cast<ImplicitParamDecl>(VD);
175 }
176
177 return nullptr;
178}
179
180void AnalysisDeclContext::registerForcedBlockExpression(const Stmt *stmt) {
181 if (!forcedBlkExprs)
182 forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs();
183 // Default construct an entry for 'stmt'.
184 if (const auto *e = dyn_cast<Expr>(stmt))
185 stmt = e->IgnoreParens();
186 (void) (*forcedBlkExprs)[stmt];
187}
188
189const CFGBlock *
190AnalysisDeclContext::getBlockForRegisteredExpression(const Stmt *stmt) {
191 assert(forcedBlkExprs)(static_cast <bool> (forcedBlkExprs) ? void (0) : __assert_fail
("forcedBlkExprs", "clang/lib/Analysis/AnalysisDeclContext.cpp"
, 191, __extension__ __PRETTY_FUNCTION__))
;
192 if (const auto *e = dyn_cast<Expr>(stmt))
193 stmt = e->IgnoreParens();
194 CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =
195 forcedBlkExprs->find(stmt);
196 assert(itr != forcedBlkExprs->end())(static_cast <bool> (itr != forcedBlkExprs->end()) ?
void (0) : __assert_fail ("itr != forcedBlkExprs->end()",
"clang/lib/Analysis/AnalysisDeclContext.cpp", 196, __extension__
__PRETTY_FUNCTION__))
;
197 return itr->second;
198}
199
200/// Add each synthetic statement in the CFG to the parent map, using the
201/// source statement's parent.
202static void addParentsForSyntheticStmts(const CFG *TheCFG, ParentMap &PM) {
203 if (!TheCFG)
204 return;
205
206 for (CFG::synthetic_stmt_iterator I = TheCFG->synthetic_stmt_begin(),
207 E = TheCFG->synthetic_stmt_end();
208 I != E; ++I) {
209 PM.setParent(I->first, PM.getParent(I->second));
210 }
211}
212
213CFG *AnalysisDeclContext::getCFG() {
214 if (!cfgBuildOptions.PruneTriviallyFalseEdges)
215 return getUnoptimizedCFG();
216
217 if (!builtCFG) {
218 cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions);
219 // Even when the cfg is not successfully built, we don't
220 // want to try building it again.
221 builtCFG = true;
222
223 if (PM)
224 addParentsForSyntheticStmts(cfg.get(), *PM);
225
226 // The Observer should only observe one build of the CFG.
227 getCFGBuildOptions().Observer = nullptr;
228 }
229 return cfg.get();
230}
231
232CFG *AnalysisDeclContext::getUnoptimizedCFG() {
233 if (!builtCompleteCFG) {
234 SaveAndRestore NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges, false);
235 completeCFG =
236 CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions);
237 // Even when the cfg is not successfully built, we don't
238 // want to try building it again.
239 builtCompleteCFG = true;
240
241 if (PM)
242 addParentsForSyntheticStmts(completeCFG.get(), *PM);
243
244 // The Observer should only observe one build of the CFG.
245 getCFGBuildOptions().Observer = nullptr;
246 }
247 return completeCFG.get();
248}
249
250CFGStmtMap *AnalysisDeclContext::getCFGStmtMap() {
251 if (cfgStmtMap)
252 return cfgStmtMap.get();
253
254 if (CFG *c = getCFG()) {
255 cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap()));
256 return cfgStmtMap.get();
257 }
258
259 return nullptr;
260}
261
262CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnalysis() {
263 if (CFA)
264 return CFA.get();
265
266 if (CFG *c = getCFG()) {
267 CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c));
268 return CFA.get();
269 }
270
271 return nullptr;
272}
273
274void AnalysisDeclContext::dumpCFG(bool ShowColors) {
275 getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
276}
277
278ParentMap &AnalysisDeclContext::getParentMap() {
279 if (!PM) {
280 PM.reset(new ParentMap(getBody()));
281 if (const auto *C = dyn_cast<CXXConstructorDecl>(getDecl())) {
282 for (const auto *I : C->inits()) {
283 PM->addStmt(I->getInit());
284 }
285 }
286 if (builtCFG)
287 addParentsForSyntheticStmts(getCFG(), *PM);
288 if (builtCompleteCFG)
289 addParentsForSyntheticStmts(getUnoptimizedCFG(), *PM);
290 }
291 return *PM;
292}
293
294AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
295 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
296 // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
297 // that has the body.
298 FD->hasBody(FD);
299 D = FD;
300 }
301
302 std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
303 if (!AC)
304 AC = std::make_unique<AnalysisDeclContext>(this, D, cfgBuildOptions);
305 return AC.get();
306}
307
308BodyFarm &AnalysisDeclContextManager::getBodyFarm() { return FunctionBodyFarm; }
309
310const StackFrameContext *
311AnalysisDeclContext::getStackFrame(const LocationContext *ParentLC,
312 const Stmt *S, const CFGBlock *Blk,
313 unsigned BlockCount, unsigned Index) {
314 return getLocationContextManager().getStackFrame(this, ParentLC, S, Blk,
315 BlockCount, Index);
316}
317
318const BlockInvocationContext *AnalysisDeclContext::getBlockInvocationContext(
319 const LocationContext *ParentLC, const BlockDecl *BD, const void *Data) {
320 return getLocationContextManager().getBlockInvocationContext(this, ParentLC,
321 BD, Data);
322}
323
324bool AnalysisDeclContext::isInStdNamespace(const Decl *D) {
325 const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext();
326 const auto *ND = dyn_cast<NamespaceDecl>(DC);
327 if (!ND)
328 return false;
329
330 while (const DeclContext *Parent = ND->getParent()) {
331 if (!isa<NamespaceDecl>(Parent))
332 break;
333 ND = cast<NamespaceDecl>(Parent);
334 }
335
336 return ND->isStdNamespace();
337}
338
339std::string AnalysisDeclContext::getFunctionName(const Decl *D) {
340 std::string Str;
341 llvm::raw_string_ostream OS(Str);
342 const ASTContext &Ctx = D->getASTContext();
343
344 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
345 OS << FD->getQualifiedNameAsString();
346
347 // In C++, there are overloads.
348
349 if (Ctx.getLangOpts().CPlusPlus) {
350 OS << '(';
351 for (const auto &P : FD->parameters()) {
352 if (P != *FD->param_begin())
353 OS << ", ";
354 OS << P->getType();
355 }
356 OS << ')';
357 }
358
359 } else if (isa<BlockDecl>(D)) {
360 PresumedLoc Loc = Ctx.getSourceManager().getPresumedLoc(D->getLocation());
361
362 if (Loc.isValid()) {
363 OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn()
364 << ')';
365 }
366
367 } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
368
369 // FIXME: copy-pasted from CGDebugInfo.cpp.
370 OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
371 const DeclContext *DC = OMD->getDeclContext();
372 if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
373 OS << OID->getName();
374 } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
375 OS << OID->getName();
376 } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
377 if (OC->IsClassExtension()) {
378 OS << OC->getClassInterface()->getName();
379 } else {
380 OS << OC->getIdentifier()->getNameStart() << '('
381 << OC->getIdentifier()->getNameStart() << ')';
382 }
383 } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
384 OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')';
385 }
386 OS << ' ' << OMD->getSelector().getAsString() << ']';
387 }
388
389 return Str;
390}
391
392LocationContextManager &AnalysisDeclContext::getLocationContextManager() {
393 assert((static_cast <bool> (ADCMgr && "Cannot create LocationContexts without an AnalysisDeclContextManager!"
) ? void (0) : __assert_fail ("ADCMgr && \"Cannot create LocationContexts without an AnalysisDeclContextManager!\""
, "clang/lib/Analysis/AnalysisDeclContext.cpp", 395, __extension__
__PRETTY_FUNCTION__))
394 ADCMgr &&(static_cast <bool> (ADCMgr && "Cannot create LocationContexts without an AnalysisDeclContextManager!"
) ? void (0) : __assert_fail ("ADCMgr && \"Cannot create LocationContexts without an AnalysisDeclContextManager!\""
, "clang/lib/Analysis/AnalysisDeclContext.cpp", 395, __extension__
__PRETTY_FUNCTION__))
395 "Cannot create LocationContexts without an AnalysisDeclContextManager!")(static_cast <bool> (ADCMgr && "Cannot create LocationContexts without an AnalysisDeclContextManager!"
) ? void (0) : __assert_fail ("ADCMgr && \"Cannot create LocationContexts without an AnalysisDeclContextManager!\""
, "clang/lib/Analysis/AnalysisDeclContext.cpp", 395, __extension__
__PRETTY_FUNCTION__))
;
396 return ADCMgr->getLocationContextManager();
397}
398
399//===----------------------------------------------------------------------===//
400// FoldingSet profiling.
401//===----------------------------------------------------------------------===//
402
403void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
404 ContextKind ck,
405 AnalysisDeclContext *ctx,
406 const LocationContext *parent,
407 const void *data) {
408 ID.AddInteger(ck);
409 ID.AddPointer(ctx);
410 ID.AddPointer(parent);
411 ID.AddPointer(data);
412}
413
414void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
415 Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block,
416 BlockCount, Index);
417}
418
419void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
420 Profile(ID, getAnalysisDeclContext(), getParent(), BD, Data);
421}
422
423//===----------------------------------------------------------------------===//
424// LocationContext creation.
425//===----------------------------------------------------------------------===//
426
427const StackFrameContext *LocationContextManager::getStackFrame(
428 AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s,
429 const CFGBlock *blk, unsigned blockCount, unsigned idx) {
430 llvm::FoldingSetNodeID ID;
431 StackFrameContext::Profile(ID, ctx, parent, s, blk, blockCount, idx);
432 void *InsertPos;
433 auto *L =
434 cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
435 if (!L) {
436 L = new StackFrameContext(ctx, parent, s, blk, blockCount, idx, ++NewID);
437 Contexts.InsertNode(L, InsertPos);
438 }
439 return L;
440}
441
442const BlockInvocationContext *LocationContextManager::getBlockInvocationContext(
443 AnalysisDeclContext *ADC, const LocationContext *ParentLC,
444 const BlockDecl *BD, const void *Data) {
445 llvm::FoldingSetNodeID ID;
446 BlockInvocationContext::Profile(ID, ADC, ParentLC, BD, Data);
447 void *InsertPos;
448 auto *L =
449 cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
450 InsertPos));
451 if (!L) {
452 L = new BlockInvocationContext(ADC, ParentLC, BD, Data, ++NewID);
453 Contexts.InsertNode(L, InsertPos);
454 }
455 return L;
456}
457
458//===----------------------------------------------------------------------===//
459// LocationContext methods.
460//===----------------------------------------------------------------------===//
461
462const StackFrameContext *LocationContext::getStackFrame() const {
463 const LocationContext *LC = this;
464 while (LC) {
465 if (const auto *SFC = dyn_cast<StackFrameContext>(LC))
466 return SFC;
467 LC = LC->getParent();
468 }
469 return nullptr;
470}
471
472bool LocationContext::inTopFrame() const {
473 return getStackFrame()->inTopFrame();
474}
475
476bool LocationContext::isParentOf(const LocationContext *LC) const {
477 do {
478 const LocationContext *Parent = LC->getParent();
479 if (Parent == this)
480 return true;
481 else
482 LC = Parent;
483 } while (LC);
484
485 return false;
486}
487
488static void printLocation(raw_ostream &Out, const SourceManager &SM,
489 SourceLocation Loc) {
490 if (Loc.isFileID() && SM.isInMainFile(Loc))
491 Out << SM.getExpansionLineNumber(Loc);
492 else
493 Loc.print(Out, SM);
494}
495
496void LocationContext::dumpStack(raw_ostream &Out) const {
497 ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
498 PrintingPolicy PP(Ctx.getLangOpts());
499 PP.TerseOutput = 1;
500
501 const SourceManager &SM =
502 getAnalysisDeclContext()->getASTContext().getSourceManager();
503
504 unsigned Frame = 0;
505 for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
506 switch (LCtx->getKind()) {
507 case StackFrame:
508 Out << "\t#" << Frame << ' ';
509 ++Frame;
510 if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
511 Out << "Calling " << AnalysisDeclContext::getFunctionName(D);
512 else
513 Out << "Calling anonymous code";
514 if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
515 Out << " at line ";
516 printLocation(Out, SM, S->getBeginLoc());
517 }
518 break;
519 case Block:
520 Out << "Invoking block";
521 if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
522 Out << " defined at line ";
523 printLocation(Out, SM, D->getBeginLoc());
524 }
525 break;
526 }
527 Out << '\n';
528 }
529}
530
531void LocationContext::printJson(raw_ostream &Out, const char *NL,
532 unsigned int Space, bool IsDot,
533 std::function<void(const LocationContext *)>
534 printMoreInfoPerContext) const {
535 ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
536 PrintingPolicy PP(Ctx.getLangOpts());
537 PP.TerseOutput = 1;
538
539 const SourceManager &SM =
540 getAnalysisDeclContext()->getASTContext().getSourceManager();
541
542 unsigned Frame = 0;
543 for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
544 Indent(Out, Space, IsDot)
545 << "{ \"lctx_id\": " << LCtx->getID() << ", \"location_context\": \"";
546 switch (LCtx->getKind()) {
547 case StackFrame:
548 Out << '#' << Frame << " Call\", \"calling\": \"";
549 ++Frame;
550 if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
551 Out << D->getQualifiedNameAsString();
552 else
553 Out << "anonymous code";
554
555 Out << "\", \"location\": ";
556 if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
557 printSourceLocationAsJson(Out, S->getBeginLoc(), SM);
558 } else {
559 Out << "null";
560 }
561
562 Out << ", \"items\": ";
563 break;
564 case Block:
565 Out << "Invoking block\" ";
566 if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
567 Out << ", \"location\": ";
568 printSourceLocationAsJson(Out, D->getBeginLoc(), SM);
569 Out << ' ';
570 }
571 break;
572 }
573
574 printMoreInfoPerContext(LCtx);
575
576 Out << '}';
577 if (LCtx->getParent())
578 Out << ',';
579 Out << NL;
580 }
581}
582
583LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void LocationContext::dump() const { printJson(llvm::errs()); }
584
585//===----------------------------------------------------------------------===//
586// Lazily generated map to query the external variables referenced by a Block.
587//===----------------------------------------------------------------------===//
588
589namespace {
590
591class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
592 BumpVector<const VarDecl *> &BEVals;
593 BumpVectorContext &BC;
594 llvm::SmallPtrSet<const VarDecl *, 4> Visited;
595 llvm::SmallPtrSet<const DeclContext *, 4> IgnoredContexts;
596
597public:
598 FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
599 BumpVectorContext &bc)
600 : BEVals(bevals), BC(bc) {}
601
602 void VisitStmt(Stmt *S) {
603 for (auto *Child : S->children())
604 if (Child)
605 Visit(Child);
606 }
607
608 void VisitDeclRefExpr(DeclRefExpr *DR) {
609 // Non-local variables are also directly modified.
610 if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
611 if (!VD->hasLocalStorage()) {
612 if (Visited.insert(VD).second)
613 BEVals.push_back(VD, BC);
614 }
615 }
616 }
617
618 void VisitBlockExpr(BlockExpr *BR) {
619 // Blocks containing blocks can transitively capture more variables.
620 IgnoredContexts.insert(BR->getBlockDecl());
621 Visit(BR->getBlockDecl()->getBody());
622 }
623
624 void VisitPseudoObjectExpr(PseudoObjectExpr *PE) {
625 for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(),
626 et = PE->semantics_end(); it != et; ++it) {
627 Expr *Semantic = *it;
628 if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
629 Semantic = OVE->getSourceExpr();
630 Visit(Semantic);
631 }
632 }
633};
634
635} // namespace
636
637using DeclVec = BumpVector<const VarDecl *>;
638
639static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
640 void *&Vec,
641 llvm::BumpPtrAllocator &A) {
642 if (Vec)
643 return (DeclVec*) Vec;
644
645 BumpVectorContext BC(A);
646 DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
647 new (BV) DeclVec(BC, 10);
648
649 // Go through the capture list.
650 for (const auto &CI : BD->captures()) {
651 BV->push_back(CI.getVariable(), BC);
652 }
653
654 // Find the referenced global/static variables.
655 FindBlockDeclRefExprsVals F(*BV, BC);
656 F.Visit(BD->getBody());
657
658 Vec = BV;
659 return BV;
660}
661
662llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
663AnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) {
664 if (!ReferencedBlockVars)
665 ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
666
667 const DeclVec *V =
668 LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
669 return llvm::make_range(V->begin(), V->end());
670}
671
672std::unique_ptr<ManagedAnalysis> &AnalysisDeclContext::getAnalysisImpl(const void *tag) {
673 if (!ManagedAnalyses)
674 ManagedAnalyses = new ManagedAnalysisMap();
675 ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses;
676 return (*M)[tag];
677}
678
679//===----------------------------------------------------------------------===//
680// Cleanup.
681//===----------------------------------------------------------------------===//
682
683ManagedAnalysis::~ManagedAnalysis() = default;
684
685AnalysisDeclContext::~AnalysisDeclContext() {
686 delete forcedBlkExprs;
687 delete ReferencedBlockVars;
688 delete (ManagedAnalysisMap*) ManagedAnalyses;
689}
690
691LocationContext::~LocationContext() = default;
692
693LocationContextManager::~LocationContextManager() {
694 clear();
695}
696
697void LocationContextManager::clear() {
698 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
699 E = Contexts.end(); I != E; ) {
700 LocationContext *LC = &*I;
701 ++I;
702 delete LC;
703 }
704 Contexts.clear();
705}