Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/Analysis/AnalysisDeclContext.cpp
Line
Count
Source (jump to first uncovered line)
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
51
using namespace clang;
52
53
using ManagedAnalysisMap = llvm::DenseMap<const void *, std::unique_ptr<ManagedAnalysis>>;
54
55
AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *ADCMgr,
56
                                         const Decl *D,
57
                                         const CFG::BuildOptions &Options)
58
0
    : ADCMgr(ADCMgr), D(D), cfgBuildOptions(Options) {
59
0
  cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
60
0
}
61
62
AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *ADCMgr,
63
                                         const Decl *D)
64
0
    : ADCMgr(ADCMgr), D(D) {
65
0
  cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
66
0
}
67
68
AnalysisDeclContextManager::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
0
      SynthesizeBodies(synthesizeBodies) {
77
0
  cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG;
78
0
  cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
79
0
  cfgBuildOptions.AddInitializers = addInitializers;
80
0
  cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
81
0
  cfgBuildOptions.AddLifetime = addLifetime;
82
0
  cfgBuildOptions.AddLoopExit = addLoopExit;
83
0
  cfgBuildOptions.AddScopes = addScopes;
84
0
  cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
85
0
  cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
86
0
  cfgBuildOptions.AddRichCXXConstructors = addRichCXXConstructors;
87
0
  cfgBuildOptions.MarkElidedCXXConstructors = markElidedCXXConstructors;
88
0
  cfgBuildOptions.AddVirtualBaseBranches = addVirtualBaseBranches;
89
0
}
90
91
0
void AnalysisDeclContextManager::clear() { Contexts.clear(); }
92
93
0
Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
94
0
  IsAutosynthesized = false;
95
0
  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
96
0
    Stmt *Body = FD->getBody();
97
0
    if (auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body))
98
0
      Body = CoroBody->getBody();
99
0
    if (ADCMgr && ADCMgr->synthesizeBodies()) {
100
0
      Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(FD);
101
0
      if (SynthesizedBody) {
102
0
        Body = SynthesizedBody;
103
0
        IsAutosynthesized = true;
104
0
      }
105
0
    }
106
0
    return Body;
107
0
  }
108
0
  else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
109
0
    Stmt *Body = MD->getBody();
110
0
    if (ADCMgr && ADCMgr->synthesizeBodies()) {
111
0
      Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(MD);
112
0
      if (SynthesizedBody) {
113
0
        Body = SynthesizedBody;
114
0
        IsAutosynthesized = true;
115
0
      }
116
0
    }
117
0
    return Body;
118
0
  } else if (const auto *BD = dyn_cast<BlockDecl>(D))
119
0
    return BD->getBody();
120
0
  else if (const auto *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
121
0
    return FunTmpl->getTemplatedDecl()->getBody();
122
123
0
  llvm_unreachable("unknown code decl");
124
0
}
125
126
0
Stmt *AnalysisDeclContext::getBody() const {
127
0
  bool Tmp;
128
0
  return getBody(Tmp);
129
0
}
130
131
0
bool AnalysisDeclContext::isBodyAutosynthesized() const {
132
0
  bool Tmp;
133
0
  getBody(Tmp);
134
0
  return Tmp;
135
0
}
136
137
0
bool AnalysisDeclContext::isBodyAutosynthesizedFromModelFile() const {
138
0
  bool Tmp;
139
0
  Stmt *Body = getBody(Tmp);
140
0
  return Tmp && Body->getBeginLoc().isValid();
141
0
}
142
143
/// Returns true if \param VD is an Objective-C implicit 'self' parameter.
144
0
static bool isSelfDecl(const VarDecl *VD) {
145
0
  return isa_and_nonnull<ImplicitParamDecl>(VD) && VD->getName() == "self";
146
0
}
147
148
0
const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
149
0
  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
150
0
    return MD->getSelfDecl();
151
0
  if (const auto *BD = dyn_cast<BlockDecl>(D)) {
152
    // See if 'self' was captured by the block.
153
0
    for (const auto &I : BD->captures()) {
154
0
      const VarDecl *VD = I.getVariable();
155
0
      if (isSelfDecl(VD))
156
0
        return dyn_cast<ImplicitParamDecl>(VD);
157
0
    }
158
0
  }
159
160
0
  auto *CXXMethod = dyn_cast<CXXMethodDecl>(D);
161
0
  if (!CXXMethod)
162
0
    return nullptr;
163
164
0
  const CXXRecordDecl *parent = CXXMethod->getParent();
165
0
  if (!parent->isLambda())
166
0
    return nullptr;
167
168
0
  for (const auto &LC : parent->captures()) {
169
0
    if (!LC.capturesVariable())
170
0
      continue;
171
172
0
    ValueDecl *VD = LC.getCapturedVar();
173
0
    if (isSelfDecl(dyn_cast<VarDecl>(VD)))
174
0
      return dyn_cast<ImplicitParamDecl>(VD);
175
0
  }
176
177
0
  return nullptr;
178
0
}
179
180
0
void AnalysisDeclContext::registerForcedBlockExpression(const Stmt *stmt) {
181
0
  if (!forcedBlkExprs)
182
0
    forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs();
183
  // Default construct an entry for 'stmt'.
184
0
  if (const auto *e = dyn_cast<Expr>(stmt))
185
0
    stmt = e->IgnoreParens();
186
0
  (void) (*forcedBlkExprs)[stmt];
187
0
}
188
189
const CFGBlock *
190
0
AnalysisDeclContext::getBlockForRegisteredExpression(const Stmt *stmt) {
191
0
  assert(forcedBlkExprs);
192
0
  if (const auto *e = dyn_cast<Expr>(stmt))
193
0
    stmt = e->IgnoreParens();
194
0
  CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =
195
0
    forcedBlkExprs->find(stmt);
196
0
  assert(itr != forcedBlkExprs->end());
197
0
  return itr->second;
198
0
}
199
200
/// Add each synthetic statement in the CFG to the parent map, using the
201
/// source statement's parent.
202
0
static void addParentsForSyntheticStmts(const CFG *TheCFG, ParentMap &PM) {
203
0
  if (!TheCFG)
204
0
    return;
205
206
0
  for (CFG::synthetic_stmt_iterator I = TheCFG->synthetic_stmt_begin(),
207
0
                                    E = TheCFG->synthetic_stmt_end();
208
0
       I != E; ++I) {
209
0
    PM.setParent(I->first, PM.getParent(I->second));
210
0
  }
211
0
}
212
213
0
CFG *AnalysisDeclContext::getCFG() {
214
0
  if (!cfgBuildOptions.PruneTriviallyFalseEdges)
215
0
    return getUnoptimizedCFG();
216
217
0
  if (!builtCFG) {
218
0
    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
0
    builtCFG = true;
222
223
0
    if (PM)
224
0
      addParentsForSyntheticStmts(cfg.get(), *PM);
225
226
    // The Observer should only observe one build of the CFG.
227
0
    getCFGBuildOptions().Observer = nullptr;
228
0
  }
229
0
  return cfg.get();
230
0
}
231
232
0
CFG *AnalysisDeclContext::getUnoptimizedCFG() {
233
0
  if (!builtCompleteCFG) {
234
0
    SaveAndRestore NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges, false);
235
0
    completeCFG =
236
0
        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
0
    builtCompleteCFG = true;
240
241
0
    if (PM)
242
0
      addParentsForSyntheticStmts(completeCFG.get(), *PM);
243
244
    // The Observer should only observe one build of the CFG.
245
0
    getCFGBuildOptions().Observer = nullptr;
246
0
  }
247
0
  return completeCFG.get();
248
0
}
249
250
0
CFGStmtMap *AnalysisDeclContext::getCFGStmtMap() {
251
0
  if (cfgStmtMap)
252
0
    return cfgStmtMap.get();
253
254
0
  if (CFG *c = getCFG()) {
255
0
    cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap()));
256
0
    return cfgStmtMap.get();
257
0
  }
258
259
0
  return nullptr;
260
0
}
261
262
0
CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnalysis() {
263
0
  if (CFA)
264
0
    return CFA.get();
265
266
0
  if (CFG *c = getCFG()) {
267
0
    CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c));
268
0
    return CFA.get();
269
0
  }
270
271
0
  return nullptr;
272
0
}
273
274
0
void AnalysisDeclContext::dumpCFG(bool ShowColors) {
275
0
  getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
276
0
}
277
278
0
ParentMap &AnalysisDeclContext::getParentMap() {
279
0
  if (!PM) {
280
0
    PM.reset(new ParentMap(getBody()));
281
0
    if (const auto *C = dyn_cast<CXXConstructorDecl>(getDecl())) {
282
0
      for (const auto *I : C->inits()) {
283
0
        PM->addStmt(I->getInit());
284
0
      }
285
0
    }
286
0
    if (builtCFG)
287
0
      addParentsForSyntheticStmts(getCFG(), *PM);
288
0
    if (builtCompleteCFG)
289
0
      addParentsForSyntheticStmts(getUnoptimizedCFG(), *PM);
290
0
  }
291
0
  return *PM;
292
0
}
293
294
0
AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
295
0
  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
296
    // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
297
    // that has the body.
298
0
    FD->hasBody(FD);
299
0
    D = FD;
300
0
  }
301
302
0
  std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
303
0
  if (!AC)
304
0
    AC = std::make_unique<AnalysisDeclContext>(this, D, cfgBuildOptions);
305
0
  return AC.get();
306
0
}
307
308
0
BodyFarm &AnalysisDeclContextManager::getBodyFarm() { return FunctionBodyFarm; }
309
310
const StackFrameContext *
311
AnalysisDeclContext::getStackFrame(const LocationContext *ParentLC,
312
                                   const Stmt *S, const CFGBlock *Blk,
313
0
                                   unsigned BlockCount, unsigned Index) {
314
0
  return getLocationContextManager().getStackFrame(this, ParentLC, S, Blk,
315
0
                                                   BlockCount, Index);
316
0
}
317
318
const BlockInvocationContext *AnalysisDeclContext::getBlockInvocationContext(
319
0
    const LocationContext *ParentLC, const BlockDecl *BD, const void *Data) {
320
0
  return getLocationContextManager().getBlockInvocationContext(this, ParentLC,
321
0
                                                               BD, Data);
322
0
}
323
324
0
bool AnalysisDeclContext::isInStdNamespace(const Decl *D) {
325
0
  const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext();
326
0
  const auto *ND = dyn_cast<NamespaceDecl>(DC);
327
0
  if (!ND)
328
0
    return false;
329
330
0
  while (const DeclContext *Parent = ND->getParent()) {
331
0
    if (!isa<NamespaceDecl>(Parent))
332
0
      break;
333
0
    ND = cast<NamespaceDecl>(Parent);
334
0
  }
335
336
0
  return ND->isStdNamespace();
337
0
}
338
339
0
std::string AnalysisDeclContext::getFunctionName(const Decl *D) {
340
0
  std::string Str;
341
0
  llvm::raw_string_ostream OS(Str);
342
0
  const ASTContext &Ctx = D->getASTContext();
343
344
0
  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
345
0
    OS << FD->getQualifiedNameAsString();
346
347
    // In C++, there are overloads.
348
349
0
    if (Ctx.getLangOpts().CPlusPlus) {
350
0
      OS << '(';
351
0
      for (const auto &P : FD->parameters()) {
352
0
        if (P != *FD->param_begin())
353
0
          OS << ", ";
354
0
        OS << P->getType();
355
0
      }
356
0
      OS << ')';
357
0
    }
358
359
0
  } else if (isa<BlockDecl>(D)) {
360
0
    PresumedLoc Loc = Ctx.getSourceManager().getPresumedLoc(D->getLocation());
361
362
0
    if (Loc.isValid()) {
363
0
      OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn()
364
0
         << ')';
365
0
    }
366
367
0
  } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
368
369
    // FIXME: copy-pasted from CGDebugInfo.cpp.
370
0
    OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
371
0
    const DeclContext *DC = OMD->getDeclContext();
372
0
    if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
373
0
      OS << OID->getName();
374
0
    } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
375
0
      OS << OID->getName();
376
0
    } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
377
0
      if (OC->IsClassExtension()) {
378
0
        OS << OC->getClassInterface()->getName();
379
0
      } else {
380
0
        OS << OC->getIdentifier()->getNameStart() << '('
381
0
           << OC->getIdentifier()->getNameStart() << ')';
382
0
      }
383
0
    } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
384
0
      OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')';
385
0
    }
386
0
    OS << ' ' << OMD->getSelector().getAsString() << ']';
387
0
  }
388
389
0
  return Str;
390
0
}
391
392
0
LocationContextManager &AnalysisDeclContext::getLocationContextManager() {
393
0
  assert(
394
0
      ADCMgr &&
395
0
      "Cannot create LocationContexts without an AnalysisDeclContextManager!");
396
0
  return ADCMgr->getLocationContextManager();
397
0
}
398
399
//===----------------------------------------------------------------------===//
400
// FoldingSet profiling.
401
//===----------------------------------------------------------------------===//
402
403
void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
404
                                    ContextKind ck,
405
                                    AnalysisDeclContext *ctx,
406
                                    const LocationContext *parent,
407
0
                                    const void *data) {
408
0
  ID.AddInteger(ck);
409
0
  ID.AddPointer(ctx);
410
0
  ID.AddPointer(parent);
411
0
  ID.AddPointer(data);
412
0
}
413
414
0
void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
415
0
  Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block,
416
0
          BlockCount, Index);
417
0
}
418
419
0
void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
420
0
  Profile(ID, getAnalysisDeclContext(), getParent(), BD, Data);
421
0
}
422
423
//===----------------------------------------------------------------------===//
424
// LocationContext creation.
425
//===----------------------------------------------------------------------===//
426
427
const StackFrameContext *LocationContextManager::getStackFrame(
428
    AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s,
429
0
    const CFGBlock *blk, unsigned blockCount, unsigned idx) {
430
0
  llvm::FoldingSetNodeID ID;
431
0
  StackFrameContext::Profile(ID, ctx, parent, s, blk, blockCount, idx);
432
0
  void *InsertPos;
433
0
  auto *L =
434
0
   cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
435
0
  if (!L) {
436
0
    L = new StackFrameContext(ctx, parent, s, blk, blockCount, idx, ++NewID);
437
0
    Contexts.InsertNode(L, InsertPos);
438
0
  }
439
0
  return L;
440
0
}
441
442
const BlockInvocationContext *LocationContextManager::getBlockInvocationContext(
443
    AnalysisDeclContext *ADC, const LocationContext *ParentLC,
444
0
    const BlockDecl *BD, const void *Data) {
445
0
  llvm::FoldingSetNodeID ID;
446
0
  BlockInvocationContext::Profile(ID, ADC, ParentLC, BD, Data);
447
0
  void *InsertPos;
448
0
  auto *L =
449
0
    cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
450
0
                                                                    InsertPos));
451
0
  if (!L) {
452
0
    L = new BlockInvocationContext(ADC, ParentLC, BD, Data, ++NewID);
453
0
    Contexts.InsertNode(L, InsertPos);
454
0
  }
455
0
  return L;
456
0
}
457
458
//===----------------------------------------------------------------------===//
459
// LocationContext methods.
460
//===----------------------------------------------------------------------===//
461
462
0
const StackFrameContext *LocationContext::getStackFrame() const {
463
0
  const LocationContext *LC = this;
464
0
  while (LC) {
465
0
    if (const auto *SFC = dyn_cast<StackFrameContext>(LC))
466
0
      return SFC;
467
0
    LC = LC->getParent();
468
0
  }
469
0
  return nullptr;
470
0
}
471
472
0
bool LocationContext::inTopFrame() const {
473
0
  return getStackFrame()->inTopFrame();
474
0
}
475
476
0
bool LocationContext::isParentOf(const LocationContext *LC) const {
477
0
  do {
478
0
    const LocationContext *Parent = LC->getParent();
479
0
    if (Parent == this)
480
0
      return true;
481
0
    else
482
0
      LC = Parent;
483
0
  } while (LC);
484
485
0
  return false;
486
0
}
487
488
static void printLocation(raw_ostream &Out, const SourceManager &SM,
489
0
                          SourceLocation Loc) {
490
0
  if (Loc.isFileID() && SM.isInMainFile(Loc))
491
0
    Out << SM.getExpansionLineNumber(Loc);
492
0
  else
493
0
    Loc.print(Out, SM);
494
0
}
495
496
0
void LocationContext::dumpStack(raw_ostream &Out) const {
497
0
  ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
498
0
  PrintingPolicy PP(Ctx.getLangOpts());
499
0
  PP.TerseOutput = 1;
500
501
0
  const SourceManager &SM =
502
0
      getAnalysisDeclContext()->getASTContext().getSourceManager();
503
504
0
  unsigned Frame = 0;
505
0
  for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
506
0
    switch (LCtx->getKind()) {
507
0
    case StackFrame:
508
0
      Out << "\t#" << Frame << ' ';
509
0
      ++Frame;
510
0
      if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
511
0
        Out << "Calling " << AnalysisDeclContext::getFunctionName(D);
512
0
      else
513
0
        Out << "Calling anonymous code";
514
0
      if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
515
0
        Out << " at line ";
516
0
        printLocation(Out, SM, S->getBeginLoc());
517
0
      }
518
0
      break;
519
0
    case Block:
520
0
      Out << "Invoking block";
521
0
      if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
522
0
        Out << " defined at line ";
523
0
        printLocation(Out, SM, D->getBeginLoc());
524
0
      }
525
0
      break;
526
0
    }
527
0
    Out << '\n';
528
0
  }
529
0
}
530
531
void LocationContext::printJson(raw_ostream &Out, const char *NL,
532
                                unsigned int Space, bool IsDot,
533
                                std::function<void(const LocationContext *)>
534
0
                                    printMoreInfoPerContext) const {
535
0
  ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
536
0
  PrintingPolicy PP(Ctx.getLangOpts());
537
0
  PP.TerseOutput = 1;
538
539
0
  const SourceManager &SM =
540
0
      getAnalysisDeclContext()->getASTContext().getSourceManager();
541
542
0
  unsigned Frame = 0;
543
0
  for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
544
0
    Indent(Out, Space, IsDot)
545
0
        << "{ \"lctx_id\": " << LCtx->getID() << ", \"location_context\": \"";
546
0
    switch (LCtx->getKind()) {
547
0
    case StackFrame:
548
0
      Out << '#' << Frame << " Call\", \"calling\": \"";
549
0
      ++Frame;
550
0
      if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
551
0
        Out << D->getQualifiedNameAsString();
552
0
      else
553
0
        Out << "anonymous code";
554
555
0
      Out << "\", \"location\": ";
556
0
      if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
557
0
        printSourceLocationAsJson(Out, S->getBeginLoc(), SM);
558
0
      } else {
559
0
        Out << "null";
560
0
      }
561
562
0
      Out << ", \"items\": ";
563
0
      break;
564
0
    case Block:
565
0
      Out << "Invoking block\" ";
566
0
      if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
567
0
        Out << ", \"location\": ";
568
0
        printSourceLocationAsJson(Out, D->getBeginLoc(), SM);
569
0
        Out << ' ';
570
0
      }
571
0
      break;
572
0
    }
573
574
0
    printMoreInfoPerContext(LCtx);
575
576
0
    Out << '}';
577
0
    if (LCtx->getParent())
578
0
      Out << ',';
579
0
    Out << NL;
580
0
  }
581
0
}
582
583
0
LLVM_DUMP_METHOD void LocationContext::dump() const { printJson(llvm::errs()); }
584
585
//===----------------------------------------------------------------------===//
586
// Lazily generated map to query the external variables referenced by a Block.
587
//===----------------------------------------------------------------------===//
588
589
namespace {
590
591
class 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
597
public:
598
  FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
599
                            BumpVectorContext &bc)
600
0
      : BEVals(bevals), BC(bc) {}
601
602
0
  void VisitStmt(Stmt *S) {
603
0
    for (auto *Child : S->children())
604
0
      if (Child)
605
0
        Visit(Child);
606
0
  }
607
608
0
  void VisitDeclRefExpr(DeclRefExpr *DR) {
609
    // Non-local variables are also directly modified.
610
0
    if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
611
0
      if (!VD->hasLocalStorage()) {
612
0
        if (Visited.insert(VD).second)
613
0
          BEVals.push_back(VD, BC);
614
0
      }
615
0
    }
616
0
  }
617
618
0
  void VisitBlockExpr(BlockExpr *BR) {
619
    // Blocks containing blocks can transitively capture more variables.
620
0
    IgnoredContexts.insert(BR->getBlockDecl());
621
0
    Visit(BR->getBlockDecl()->getBody());
622
0
  }
623
624
0
  void VisitPseudoObjectExpr(PseudoObjectExpr *PE) {
625
0
    for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(),
626
0
         et = PE->semantics_end(); it != et; ++it) {
627
0
      Expr *Semantic = *it;
628
0
      if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
629
0
        Semantic = OVE->getSourceExpr();
630
0
      Visit(Semantic);
631
0
    }
632
0
  }
633
};
634
635
} // namespace
636
637
using DeclVec = BumpVector<const VarDecl *>;
638
639
static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
640
                                              void *&Vec,
641
0
                                              llvm::BumpPtrAllocator &A) {
642
0
  if (Vec)
643
0
    return (DeclVec*) Vec;
644
645
0
  BumpVectorContext BC(A);
646
0
  DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
647
0
  new (BV) DeclVec(BC, 10);
648
649
  // Go through the capture list.
650
0
  for (const auto &CI : BD->captures()) {
651
0
    BV->push_back(CI.getVariable(), BC);
652
0
  }
653
654
  // Find the referenced global/static variables.
655
0
  FindBlockDeclRefExprsVals F(*BV, BC);
656
0
  F.Visit(BD->getBody());
657
658
0
  Vec = BV;
659
0
  return BV;
660
0
}
661
662
llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
663
0
AnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) {
664
0
  if (!ReferencedBlockVars)
665
0
    ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
666
667
0
  const DeclVec *V =
668
0
      LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
669
0
  return llvm::make_range(V->begin(), V->end());
670
0
}
671
672
0
std::unique_ptr<ManagedAnalysis> &AnalysisDeclContext::getAnalysisImpl(const void *tag) {
673
0
  if (!ManagedAnalyses)
674
0
    ManagedAnalyses = new ManagedAnalysisMap();
675
0
  ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses;
676
0
  return (*M)[tag];
677
0
}
678
679
//===----------------------------------------------------------------------===//
680
// Cleanup.
681
//===----------------------------------------------------------------------===//
682
683
0
ManagedAnalysis::~ManagedAnalysis() = default;
684
685
0
AnalysisDeclContext::~AnalysisDeclContext() {
686
0
  delete forcedBlkExprs;
687
0
  delete ReferencedBlockVars;
688
0
  delete (ManagedAnalysisMap*) ManagedAnalyses;
689
0
}
690
691
0
LocationContext::~LocationContext() = default;
692
693
0
LocationContextManager::~LocationContextManager() {
694
0
  clear();
695
0
}
696
697
0
void LocationContextManager::clear() {
698
0
  for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
699
0
       E = Contexts.end(); I != E; ) {
700
0
    LocationContext *LC = &*I;
701
0
    ++I;
702
0
    delete LC;
703
0
  }
704
0
  Contexts.clear();
705
0
}