Coverage Report

Created: 2020-02-18 08:44

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Analysis/PathDiagnostic.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -------------===//
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 PathDiagnostic-related interfaces.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "clang/Analysis/PathDiagnostic.h"
14
#include "clang/AST/Decl.h"
15
#include "clang/AST/DeclBase.h"
16
#include "clang/AST/DeclCXX.h"
17
#include "clang/AST/DeclObjC.h"
18
#include "clang/AST/DeclTemplate.h"
19
#include "clang/AST/Expr.h"
20
#include "clang/AST/ExprCXX.h"
21
#include "clang/AST/OperationKinds.h"
22
#include "clang/AST/ParentMap.h"
23
#include "clang/AST/Stmt.h"
24
#include "clang/AST/Type.h"
25
#include "clang/Analysis/AnalysisDeclContext.h"
26
#include "clang/Analysis/CFG.h"
27
#include "clang/Analysis/ProgramPoint.h"
28
#include "clang/Basic/FileManager.h"
29
#include "clang/Basic/LLVM.h"
30
#include "clang/Basic/SourceLocation.h"
31
#include "clang/Basic/SourceManager.h"
32
#include "llvm/ADT/ArrayRef.h"
33
#include "llvm/ADT/FoldingSet.h"
34
#include "llvm/ADT/None.h"
35
#include "llvm/ADT/Optional.h"
36
#include "llvm/ADT/STLExtras.h"
37
#include "llvm/ADT/SmallString.h"
38
#include "llvm/ADT/SmallVector.h"
39
#include "llvm/ADT/StringExtras.h"
40
#include "llvm/ADT/StringRef.h"
41
#include "llvm/Support/Casting.h"
42
#include "llvm/Support/ErrorHandling.h"
43
#include "llvm/Support/raw_ostream.h"
44
#include <cassert>
45
#include <cstring>
46
#include <memory>
47
#include <utility>
48
#include <vector>
49
50
using namespace clang;
51
using namespace ento;
52
53
125k
static StringRef StripTrailingDots(StringRef s) {
54
126k
  for (StringRef::size_type i = s.size(); i != 0; 
--i1.12k
)
55
101k
    if (s[i - 1] != '.')
56
100k
      return s.substr(0, i);
57
125k
  
return {}24.6k
;
58
125k
}
59
60
PathDiagnosticPiece::PathDiagnosticPiece(StringRef s,
61
                                         Kind k, DisplayHint hint)
62
26.5k
    : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
63
64
PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
65
19.2k
    : kind(k), Hint(hint) {}
66
67
45.7k
PathDiagnosticPiece::~PathDiagnosticPiece() = default;
68
69
24.6k
PathDiagnosticEventPiece::~PathDiagnosticEventPiece() = default;
70
71
6.72k
PathDiagnosticCallPiece::~PathDiagnosticCallPiece() = default;
72
73
13.3k
PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() = default;
74
75
39
PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() = default;
76
77
166
PathDiagnosticNotePiece::~PathDiagnosticNotePiece() = default;
78
79
917
PathDiagnosticPopUpPiece::~PathDiagnosticPopUpPiece() = default;
80
81
void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
82
15.5k
                           bool ShouldFlattenMacros) const {
83
23.6k
  for (auto &Piece : *this) {
84
23.6k
    switch (Piece->getKind()) {
85
681
    case PathDiagnosticPiece::Call: {
86
681
      auto &Call = cast<PathDiagnosticCallPiece>(*Piece);
87
681
      if (auto CallEnter = Call.getCallEnterEvent())
88
678
        Current.push_back(std::move(CallEnter));
89
681
      Call.path.flattenTo(Primary, Primary, ShouldFlattenMacros);
90
681
      if (auto callExit = Call.getCallExitEvent())
91
427
        Current.push_back(std::move(callExit));
92
681
      break;
93
0
    }
94
39
    case PathDiagnosticPiece::Macro: {
95
39
      auto &Macro = cast<PathDiagnosticMacroPiece>(*Piece);
96
39
      if (ShouldFlattenMacros) {
97
39
        Macro.subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
98
39
      } else {
99
0
        Current.push_back(Piece);
100
0
        PathPieces NewPath;
101
0
        Macro.subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
102
0
        // FIXME: This probably shouldn't mutate the original path piece.
103
0
        Macro.subPieces = NewPath;
104
0
      }
105
39
      break;
106
0
    }
107
22.9k
    case PathDiagnosticPiece::Event:
108
22.9k
    case PathDiagnosticPiece::ControlFlow:
109
22.9k
    case PathDiagnosticPiece::Note:
110
22.9k
    case PathDiagnosticPiece::PopUp:
111
22.9k
      Current.push_back(Piece);
112
22.9k
      break;
113
23.6k
    }
114
23.6k
  }
115
15.5k
}
116
117
24.6k
PathDiagnostic::~PathDiagnostic() = default;
118
119
PathDiagnostic::PathDiagnostic(
120
    StringRef CheckerName, const Decl *declWithIssue, StringRef bugtype,
121
    StringRef verboseDesc, StringRef shortDesc, StringRef category,
122
    PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique,
123
    std::unique_ptr<FilesToLineNumsMap> ExecutedLines)
124
    : CheckerName(CheckerName), DeclWithIssue(declWithIssue),
125
      BugType(StripTrailingDots(bugtype)),
126
      VerboseDesc(StripTrailingDots(verboseDesc)),
127
      ShortDesc(StripTrailingDots(shortDesc)),
128
      Category(StripTrailingDots(category)), UniqueingLoc(LocationToUnique),
129
      UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)),
130
24.6k
      path(pathImpl) {}
131
132
0
void PathDiagnosticConsumer::anchor() {}
133
134
1.35k
PathDiagnosticConsumer::~PathDiagnosticConsumer() {
135
1.35k
  // Delete the contents of the FoldingSet if it isn't empty already.
136
1.35k
  for (auto &Diag : Diags)
137
0
    delete &Diag;
138
1.35k
}
139
140
void PathDiagnosticConsumer::HandlePathDiagnostic(
141
13.7k
    std::unique_ptr<PathDiagnostic> D) {
142
13.7k
  if (!D || D->path.empty())
143
0
    return;
144
13.7k
145
13.7k
  // We need to flatten the locations (convert Stmt* to locations) because
146
13.7k
  // the referenced statements may be freed by the time the diagnostics
147
13.7k
  // are emitted.
148
13.7k
  D->flattenLocations();
149
13.7k
150
13.7k
  // If the PathDiagnosticConsumer does not support diagnostics that
151
13.7k
  // cross file boundaries, prune out such diagnostics now.
152
13.7k
  if (!supportsCrossFileDiagnostics()) {
153
475
    // Verify that the entire path is from the same FileID.
154
475
    FileID FID;
155
475
    const SourceManager &SMgr = D->path.front()->getLocation().getManager();
156
475
    SmallVector<const PathPieces *, 5> WorkList;
157
475
    WorkList.push_back(&D->path);
158
475
    SmallString<128> buf;
159
475
    llvm::raw_svector_ostream warning(buf);
160
475
    warning << "warning: Path diagnostic report is not generated. Current "
161
475
            << "output format does not support diagnostics that cross file "
162
475
            << "boundaries. Refer to --analyzer-output for valid output "
163
475
            << "formats\n";
164
475
165
1.05k
    while (!WorkList.empty()) {
166
582
      const PathPieces &path = *WorkList.pop_back_val();
167
582
168
3.12k
      for (const auto &I : path) {
169
3.12k
        const PathDiagnosticPiece *piece = I.get();
170
3.12k
        FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc();
171
3.12k
172
3.12k
        if (FID.isInvalid()) {
173
475
          FID = SMgr.getFileID(L);
174
2.65k
        } else if (SMgr.getFileID(L) != FID) {
175
1
          llvm::errs() << warning.str();
176
1
          return;
177
1
        }
178
3.12k
179
3.12k
        // Check the source ranges.
180
3.12k
        ArrayRef<SourceRange> Ranges = piece->getRanges();
181
3.12k
        for (const auto &I : Ranges) {
182
1.29k
          SourceLocation L = SMgr.getExpansionLoc(I.getBegin());
183
1.29k
          if (!L.isFileID() || SMgr.getFileID(L) != FID) {
184
0
            llvm::errs() << warning.str();
185
0
            return;
186
0
          }
187
1.29k
          L = SMgr.getExpansionLoc(I.getEnd());
188
1.29k
          if (!L.isFileID() || SMgr.getFileID(L) != FID) {
189
0
            llvm::errs() << warning.str();
190
0
            return;
191
0
          }
192
1.29k
        }
193
3.12k
194
3.12k
        if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece))
195
76
          WorkList.push_back(&call->path);
196
3.05k
        else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece))
197
31
          WorkList.push_back(&macro->subPieces);
198
3.12k
      }
199
582
    }
200
475
201
475
    
if (474
FID.isInvalid()474
)
202
0
      return; // FIXME: Emit a warning?
203
13.7k
  }
204
13.7k
205
13.7k
  // Profile the node to see if we already have something matching it
206
13.7k
  llvm::FoldingSetNodeID profile;
207
13.7k
  D->Profile(profile);
208
13.7k
  void *InsertPos = nullptr;
209
13.7k
210
13.7k
  if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
211
63
    // Keep the PathDiagnostic with the shorter path.
212
63
    // Note, the enclosing routine is called in deterministic order, so the
213
63
    // results will be consistent between runs (no reason to break ties if the
214
63
    // size is the same).
215
63
    const unsigned orig_size = orig->full_size();
216
63
    const unsigned new_size = D->full_size();
217
63
    if (orig_size <= new_size)
218
63
      return;
219
0
220
0
    assert(orig != D.get());
221
0
    Diags.RemoveNode(orig);
222
0
    delete orig;
223
0
  }
224
13.7k
225
13.7k
  Diags.InsertNode(D.release());
226
13.7k
}
227
228
static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y);
229
230
static Optional<bool>
231
compareControlFlow(const PathDiagnosticControlFlowPiece &X,
232
0
                   const PathDiagnosticControlFlowPiece &Y) {
233
0
  FullSourceLoc XSL = X.getStartLocation().asLocation();
234
0
  FullSourceLoc YSL = Y.getStartLocation().asLocation();
235
0
  if (XSL != YSL)
236
0
    return XSL.isBeforeInTranslationUnitThan(YSL);
237
0
  FullSourceLoc XEL = X.getEndLocation().asLocation();
238
0
  FullSourceLoc YEL = Y.getEndLocation().asLocation();
239
0
  if (XEL != YEL)
240
0
    return XEL.isBeforeInTranslationUnitThan(YEL);
241
0
  return None;
242
0
}
243
244
static Optional<bool> compareMacro(const PathDiagnosticMacroPiece &X,
245
0
                                   const PathDiagnosticMacroPiece &Y) {
246
0
  return comparePath(X.subPieces, Y.subPieces);
247
0
}
248
249
static Optional<bool> compareCall(const PathDiagnosticCallPiece &X,
250
0
                                  const PathDiagnosticCallPiece &Y) {
251
0
  FullSourceLoc X_CEL = X.callEnter.asLocation();
252
0
  FullSourceLoc Y_CEL = Y.callEnter.asLocation();
253
0
  if (X_CEL != Y_CEL)
254
0
    return X_CEL.isBeforeInTranslationUnitThan(Y_CEL);
255
0
  FullSourceLoc X_CEWL = X.callEnterWithin.asLocation();
256
0
  FullSourceLoc Y_CEWL = Y.callEnterWithin.asLocation();
257
0
  if (X_CEWL != Y_CEWL)
258
0
    return X_CEWL.isBeforeInTranslationUnitThan(Y_CEWL);
259
0
  FullSourceLoc X_CRL = X.callReturn.asLocation();
260
0
  FullSourceLoc Y_CRL = Y.callReturn.asLocation();
261
0
  if (X_CRL != Y_CRL)
262
0
    return X_CRL.isBeforeInTranslationUnitThan(Y_CRL);
263
0
  return comparePath(X.path, Y.path);
264
0
}
265
266
static Optional<bool> comparePiece(const PathDiagnosticPiece &X,
267
8
                                   const PathDiagnosticPiece &Y) {
268
8
  if (X.getKind() != Y.getKind())
269
0
    return X.getKind() < Y.getKind();
270
8
271
8
  FullSourceLoc XL = X.getLocation().asLocation();
272
8
  FullSourceLoc YL = Y.getLocation().asLocation();
273
8
  if (XL != YL)
274
0
    return XL.isBeforeInTranslationUnitThan(YL);
275
8
276
8
  if (X.getString() != Y.getString())
277
0
    return X.getString() < Y.getString();
278
8
279
8
  if (X.getRanges().size() != Y.getRanges().size())
280
2
    return X.getRanges().size() < Y.getRanges().size();
281
6
282
6
  const SourceManager &SM = XL.getManager();
283
6
284
6
  for (unsigned i = 0, n = X.getRanges().size(); i < n; 
++i0
) {
285
6
    SourceRange XR = X.getRanges()[i];
286
6
    SourceRange YR = Y.getRanges()[i];
287
6
    if (XR != YR) {
288
6
      if (XR.getBegin() != YR.getBegin())
289
0
        return SM.isBeforeInTranslationUnit(XR.getBegin(), YR.getBegin());
290
6
      return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd());
291
6
    }
292
6
  }
293
6
294
6
  
switch (X.getKind()) 0
{
295
0
    case PathDiagnosticPiece::ControlFlow:
296
0
      return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X),
297
0
                                cast<PathDiagnosticControlFlowPiece>(Y));
298
0
    case PathDiagnosticPiece::Macro:
299
0
      return compareMacro(cast<PathDiagnosticMacroPiece>(X),
300
0
                          cast<PathDiagnosticMacroPiece>(Y));
301
0
    case PathDiagnosticPiece::Call:
302
0
      return compareCall(cast<PathDiagnosticCallPiece>(X),
303
0
                         cast<PathDiagnosticCallPiece>(Y));
304
0
    case PathDiagnosticPiece::Event:
305
0
    case PathDiagnosticPiece::Note:
306
0
    case PathDiagnosticPiece::PopUp:
307
0
      return None;
308
0
  }
309
0
  llvm_unreachable("all cases handled");
310
0
}
311
312
10
static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) {
313
10
  if (X.size() != Y.size())
314
2
    return X.size() < Y.size();
315
8
316
8
  PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
317
8
  PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
318
8
319
8
  for ( ; X_I != X_end && Y_I != Y_end; 
++X_I, ++Y_I0
) {
320
8
    Optional<bool> b = comparePiece(**X_I, **Y_I);
321
8
    if (b.hasValue())
322
8
      return b.getValue();
323
8
  }
324
8
325
8
  
return None0
;
326
8
}
327
328
109k
static bool compareCrossTUSourceLocs(FullSourceLoc XL, FullSourceLoc YL) {
329
109k
  std::pair<FileID, unsigned> XOffs = XL.getDecomposedLoc();
330
109k
  std::pair<FileID, unsigned> YOffs = YL.getDecomposedLoc();
331
109k
  const SourceManager &SM = XL.getManager();
332
109k
  std::pair<bool, bool> InSameTU = SM.isInTheSameTranslationUnit(XOffs, YOffs);
333
109k
  if (InSameTU.first)
334
109k
    return XL.isBeforeInTranslationUnitThan(YL);
335
0
  const FileEntry *XFE = SM.getFileEntryForID(XL.getSpellingLoc().getFileID());
336
0
  const FileEntry *YFE = SM.getFileEntryForID(YL.getSpellingLoc().getFileID());
337
0
  if (!XFE || !YFE)
338
0
    return XFE && !YFE;
339
0
  int NameCmp = XFE->getName().compare(YFE->getName());
340
0
  if (NameCmp != 0)
341
0
    return NameCmp == -1;
342
0
  // Last resort: Compare raw file IDs that are possibly expansions.
343
0
  return XL.getFileID() < YL.getFileID();
344
0
}
345
346
109k
static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
347
109k
  FullSourceLoc XL = X.getLocation().asLocation();
348
109k
  FullSourceLoc YL = Y.getLocation().asLocation();
349
109k
  if (XL != YL)
350
109k
    return compareCrossTUSourceLocs(XL, YL);
351
317
  if (X.getBugType() != Y.getBugType())
352
45
    return X.getBugType() < Y.getBugType();
353
272
  if (X.getCategory() != Y.getCategory())
354
0
    return X.getCategory() < Y.getCategory();
355
272
  if (X.getVerboseDescription() != Y.getVerboseDescription())
356
262
    return X.getVerboseDescription() < Y.getVerboseDescription();
357
10
  if (X.getShortDescription() != Y.getShortDescription())
358
0
    return X.getShortDescription() < Y.getShortDescription();
359
10
  if (X.getDeclWithIssue() != Y.getDeclWithIssue()) {
360
0
    const Decl *XD = X.getDeclWithIssue();
361
0
    if (!XD)
362
0
      return true;
363
0
    const Decl *YD = Y.getDeclWithIssue();
364
0
    if (!YD)
365
0
      return false;
366
0
    SourceLocation XDL = XD->getLocation();
367
0
    SourceLocation YDL = YD->getLocation();
368
0
    if (XDL != YDL) {
369
0
      const SourceManager &SM = XL.getManager();
370
0
      return compareCrossTUSourceLocs(FullSourceLoc(XDL, SM),
371
0
                                      FullSourceLoc(YDL, SM));
372
0
    }
373
10
  }
374
10
  PathDiagnostic::meta_iterator XI = X.meta_begin(), XE = X.meta_end();
375
10
  PathDiagnostic::meta_iterator YI = Y.meta_begin(), YE = Y.meta_end();
376
10
  if (XE - XI != YE - YI)
377
0
    return (XE - XI) < (YE - YI);
378
10
  for ( ; XI != XE ; 
++XI, ++YI0
) {
379
0
    if (*XI != *YI)
380
0
      return (*XI) < (*YI);
381
0
  }
382
10
  Optional<bool> b = comparePath(X.path, Y.path);
383
10
  assert(b.hasValue());
384
10
  return b.getValue();
385
10
}
386
387
void PathDiagnosticConsumer::FlushDiagnostics(
388
1.39k
                                     PathDiagnosticConsumer::FilesMade *Files) {
389
1.39k
  if (flushed)
390
41
    return;
391
1.35k
392
1.35k
  flushed = true;
393
1.35k
394
1.35k
  std::vector<const PathDiagnostic *> BatchDiags;
395
1.35k
  for (const auto &D : Diags)
396
13.7k
    BatchDiags.push_back(&D);
397
1.35k
398
1.35k
  // Sort the diagnostics so that they are always emitted in a deterministic
399
1.35k
  // order.
400
1.35k
  int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
401
71.0k
      [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
402
71.0k
        assert(*X != *Y && "PathDiagnostics not uniqued!");
403
71.0k
        if (compare(**X, **Y))
404
32.6k
          return -1;
405
38.4k
        assert(compare(**Y, **X) && "Not a total order!");
406
38.4k
        return 1;
407
38.4k
      };
408
1.35k
  array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
409
1.35k
410
1.35k
  FlushDiagnosticsImpl(BatchDiags, Files);
411
1.35k
412
1.35k
  // Delete the flushed diagnostics.
413
1.35k
  for (const auto D : BatchDiags)
414
13.7k
    delete D;
415
1.35k
416
1.35k
  // Clear out the FoldingSet.
417
1.35k
  Diags.clear();
418
1.35k
}
419
420
1.25k
PathDiagnosticConsumer::FilesMade::~FilesMade() {
421
1.25k
  for (PDFileEntry &Entry : Set)
422
90
    Entry.~PDFileEntry();
423
1.25k
}
424
425
void PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD,
426
                                                      StringRef ConsumerName,
427
90
                                                      StringRef FileName) {
428
90
  llvm::FoldingSetNodeID NodeID;
429
90
  NodeID.Add(PD);
430
90
  void *InsertPos;
431
90
  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
432
90
  if (!Entry) {
433
90
    Entry = Alloc.Allocate<PDFileEntry>();
434
90
    Entry = new (Entry) PDFileEntry(NodeID);
435
90
    Set.InsertNode(Entry, InsertPos);
436
90
  }
437
90
438
90
  // Allocate persistent storage for the file name.
439
90
  char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
440
90
  memcpy(FileName_cstr, FileName.data(), FileName.size());
441
90
442
90
  Entry->files.push_back(std::make_pair(ConsumerName,
443
90
                                        StringRef(FileName_cstr,
444
90
                                                  FileName.size())));
445
90
}
446
447
PathDiagnosticConsumer::PDFileEntry::ConsumerFiles *
448
2
PathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) {
449
2
  llvm::FoldingSetNodeID NodeID;
450
2
  NodeID.Add(PD);
451
2
  void *InsertPos;
452
2
  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
453
2
  if (!Entry)
454
0
    return nullptr;
455
2
  return &Entry->files;
456
2
}
457
458
//===----------------------------------------------------------------------===//
459
// PathDiagnosticLocation methods.
460
//===----------------------------------------------------------------------===//
461
462
SourceLocation PathDiagnosticLocation::getValidSourceLocation(
463
87.6k
    const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEndOfStatement) {
464
87.6k
  SourceLocation L = UseEndOfStatement ? 
S->getEndLoc()5
:
S->getBeginLoc()87.6k
;
465
87.6k
  assert(!LAC.isNull() &&
466
87.6k
         "A valid LocationContext or AnalysisDeclContext should be passed to "
467
87.6k
         "PathDiagnosticLocation upon creation.");
468
87.6k
469
87.6k
  // S might be a temporary statement that does not have a location in the
470
87.6k
  // source code, so find an enclosing statement and use its location.
471
87.6k
  if (!L.isValid()) {
472
49
    AnalysisDeclContext *ADC;
473
49
    if (LAC.is<const LocationContext*>())
474
49
      ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext();
475
0
    else
476
0
      ADC = LAC.get<AnalysisDeclContext*>();
477
49
478
49
    ParentMap &PM = ADC->getParentMap();
479
49
480
49
    const Stmt *Parent = S;
481
51
    do {
482
51
      Parent = PM.getParent(Parent);
483
51
484
51
      // In rare cases, we have implicit top-level expressions,
485
51
      // such as arguments for implicit member initializers.
486
51
      // In this case, fall back to the start of the body (even if we were
487
51
      // asked for the statement end location).
488
51
      if (!Parent) {
489
47
        const Stmt *Body = ADC->getBody();
490
47
        if (Body)
491
47
          L = Body->getBeginLoc();
492
0
        else
493
0
          L = ADC->getDecl()->getEndLoc();
494
47
        break;
495
47
      }
496
4
497
4
      L = UseEndOfStatement ? 
Parent->getEndLoc()0
: Parent->getBeginLoc();
498
4
    } while (!L.isValid());
499
49
  }
500
87.6k
501
87.6k
  // FIXME: Ironically, this assert actually fails in some cases.
502
87.6k
  //assert(L.isValid());
503
87.6k
  return L;
504
87.6k
}
505
506
static PathDiagnosticLocation
507
getLocationForCaller(const StackFrameContext *SFC,
508
                     const LocationContext *CallerCtx,
509
13.2k
                     const SourceManager &SM) {
510
13.2k
  const CFGBlock &Block = *SFC->getCallSiteBlock();
511
13.2k
  CFGElement Source = Block[SFC->getIndex()];
512
13.2k
513
13.2k
  switch (Source.getKind()) {
514
13.2k
  case CFGElement::Statement:
515
13.2k
  case CFGElement::Constructor:
516
13.2k
  case CFGElement::CXXRecordTypedCall:
517
13.2k
    return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
518
13.2k
                                  SM, CallerCtx);
519
13.2k
  case CFGElement::Initializer: {
520
0
    const CFGInitializer &Init = Source.castAs<CFGInitializer>();
521
0
    return PathDiagnosticLocation(Init.getInitializer()->getInit(),
522
0
                                  SM, CallerCtx);
523
13.2k
  }
524
13.2k
  case CFGElement::AutomaticObjectDtor: {
525
13
    const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
526
13
    return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(),
527
13
                                             SM, CallerCtx);
528
13.2k
  }
529
13.2k
  case CFGElement::DeleteDtor: {
530
24
    const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
531
24
    return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
532
13.2k
  }
533
13.2k
  case CFGElement::BaseDtor:
534
2
  case CFGElement::MemberDtor: {
535
2
    const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
536
2
    if (const Stmt *CallerBody = CallerInfo->getBody())
537
2
      return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
538
0
    return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
539
0
  }
540
32
  case CFGElement::NewAllocator: {
541
32
    const CFGNewAllocator &Alloc = Source.castAs<CFGNewAllocator>();
542
32
    return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerCtx);
543
0
  }
544
3
  case CFGElement::TemporaryDtor: {
545
3
    // Temporary destructors are for temporaries. They die immediately at around
546
3
    // the location of CXXBindTemporaryExpr. If they are lifetime-extended,
547
3
    // they'd be dealt with via an AutomaticObjectDtor instead.
548
3
    const auto &Dtor = Source.castAs<CFGTemporaryDtor>();
549
3
    return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM,
550
3
                                             CallerCtx);
551
0
  }
552
0
  case CFGElement::ScopeBegin:
553
0
  case CFGElement::ScopeEnd:
554
0
    llvm_unreachable("not yet implemented!");
555
0
  case CFGElement::LifetimeEnds:
556
0
  case CFGElement::LoopExit:
557
0
    llvm_unreachable("CFGElement kind should not be on callsite!");
558
0
  }
559
0
560
0
  llvm_unreachable("Unknown CFGElement kind");
561
0
}
562
563
PathDiagnosticLocation
564
PathDiagnosticLocation::createBegin(const Decl *D,
565
8.24k
                                    const SourceManager &SM) {
566
8.24k
  return PathDiagnosticLocation(D->getBeginLoc(), SM, SingleLocK);
567
8.24k
}
568
569
PathDiagnosticLocation
570
PathDiagnosticLocation::createBegin(const Stmt *S,
571
                                    const SourceManager &SM,
572
3.01k
                                    LocationOrAnalysisDeclContext LAC) {
573
3.01k
  return PathDiagnosticLocation(getValidSourceLocation(S, LAC),
574
3.01k
                                SM, SingleLocK);
575
3.01k
}
576
577
PathDiagnosticLocation
578
PathDiagnosticLocation::createEnd(const Stmt *S,
579
                                  const SourceManager &SM,
580
725
                                  LocationOrAnalysisDeclContext LAC) {
581
725
  if (const auto *CS = dyn_cast<CompoundStmt>(S))
582
720
    return createEndBrace(CS, SM);
583
5
  return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
584
5
                                SM, SingleLocK);
585
5
}
586
587
PathDiagnosticLocation
588
PathDiagnosticLocation::createOperatorLoc(const BinaryOperator *BO,
589
3.38k
                                          const SourceManager &SM) {
590
3.38k
  return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
591
3.38k
}
592
593
PathDiagnosticLocation
594
PathDiagnosticLocation::createConditionalColonLoc(
595
                                            const ConditionalOperator *CO,
596
16
                                            const SourceManager &SM) {
597
16
  return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
598
16
}
599
600
PathDiagnosticLocation
601
PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME,
602
10
                                        const SourceManager &SM) {
603
10
604
10
  assert(ME->getMemberLoc().isValid() || ME->getBeginLoc().isValid());
605
10
606
10
  // In some cases, getMemberLoc isn't valid -- in this case we'll return with
607
10
  // some other related valid SourceLocation.
608
10
  if (ME->getMemberLoc().isValid())
609
6
    return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
610
4
611
4
  return PathDiagnosticLocation(ME->getBeginLoc(), SM, SingleLocK);
612
4
}
613
614
PathDiagnosticLocation
615
PathDiagnosticLocation::createBeginBrace(const CompoundStmt *CS,
616
0
                                         const SourceManager &SM) {
617
0
  SourceLocation L = CS->getLBracLoc();
618
0
  return PathDiagnosticLocation(L, SM, SingleLocK);
619
0
}
620
621
PathDiagnosticLocation
622
PathDiagnosticLocation::createEndBrace(const CompoundStmt *CS,
623
745
                                       const SourceManager &SM) {
624
745
  SourceLocation L = CS->getRBracLoc();
625
745
  return PathDiagnosticLocation(L, SM, SingleLocK);
626
745
}
627
628
PathDiagnosticLocation
629
PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
630
0
                                        const SourceManager &SM) {
631
0
  // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
632
0
  if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
633
0
    if (!CS->body_empty()) {
634
0
      SourceLocation Loc = (*CS->body_begin())->getBeginLoc();
635
0
      return PathDiagnosticLocation(Loc, SM, SingleLocK);
636
0
    }
637
0
638
0
  return PathDiagnosticLocation();
639
0
}
640
641
PathDiagnosticLocation
642
PathDiagnosticLocation::createDeclEnd(const LocationContext *LC,
643
153
                                      const SourceManager &SM) {
644
153
  SourceLocation L = LC->getDecl()->getBodyRBrace();
645
153
  return PathDiagnosticLocation(L, SM, SingleLocK);
646
153
}
647
648
PathDiagnosticLocation
649
PathDiagnosticLocation::create(const ProgramPoint& P,
650
2.10k
                               const SourceManager &SMng) {
651
2.10k
  const Stmt* S = nullptr;
652
2.10k
  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
653
312
    const CFGBlock *BSrc = BE->getSrc();
654
312
    if (BSrc->getTerminator().isVirtualBaseBranch()) {
655
110
      // TODO: VirtualBaseBranches should also appear for destructors.
656
110
      // In this case we should put the diagnostic at the end of decl.
657
110
      return PathDiagnosticLocation::createBegin(
658
110
          P.getLocationContext()->getDecl(), SMng);
659
110
660
202
    } else {
661
202
      S = BSrc->getTerminatorCondition();
662
202
      if (!S) {
663
10
        // If the BlockEdge has no terminator condition statement but its
664
10
        // source is the entry of the CFG (e.g. a checker crated the branch at
665
10
        // the beginning of a function), use the function's declaration instead.
666
10
        assert(BSrc == &BSrc->getParent()->getEntry() && "CFGBlock has no "
667
10
               "TerminatorCondition and is not the enrty block of the CFG");
668
10
        return PathDiagnosticLocation::createBegin(
669
10
            P.getLocationContext()->getDecl(), SMng);
670
10
      }
671
1.79k
    }
672
1.79k
  } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
673
1.70k
    S = SP->getStmt();
674
1.70k
    if (P.getAs<PostStmtPurgeDeadSymbols>())
675
0
      return PathDiagnosticLocation::createEnd(S, SMng, P.getLocationContext());
676
93
  } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
677
6
    return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
678
6
                                  SMng);
679
87
  } else if (Optional<PreImplicitCall> PIC = P.getAs<PreImplicitCall>()) {
680
0
    return PathDiagnosticLocation(PIC->getLocation(), SMng);
681
87
  } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
682
0
    return PathDiagnosticLocation(PIE->getLocation(), SMng);
683
87
  } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
684
3
    return getLocationForCaller(CE->getCalleeContext(),
685
3
                                CE->getLocationContext(),
686
3
                                SMng);
687
84
  } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
688
0
    return getLocationForCaller(CEE->getCalleeContext(),
689
0
                                CEE->getLocationContext(),
690
0
                                SMng);
691
84
  } else if (auto CEB = P.getAs<CallExitBegin>()) {
692
78
    if (const ReturnStmt *RS = CEB->getReturnStmt())
693
30
      return PathDiagnosticLocation::createBegin(RS, SMng,
694
30
                                                 CEB->getLocationContext());
695
48
    return PathDiagnosticLocation(
696
48
        CEB->getLocationContext()->getDecl()->getSourceRange().getEnd(), SMng);
697
48
  } else 
if (Optional<BlockEntrance> 6
BE6
= P.getAs<BlockEntrance>()) {
698
5
    if (Optional<CFGElement> BlockFront = BE->getFirstElement()) {
699
4
      if (auto StmtElt = BlockFront->getAs<CFGStmt>()) {
700
3
        return PathDiagnosticLocation(StmtElt->getStmt()->getBeginLoc(), SMng);
701
3
      } else 
if (auto 1
NewAllocElt1
= BlockFront->getAs<CFGNewAllocator>()) {
702
1
        return PathDiagnosticLocation(
703
1
            NewAllocElt->getAllocatorExpr()->getBeginLoc(), SMng);
704
1
      }
705
0
      llvm_unreachable("Unexpected CFG element at front of block");
706
0
    }
707
1
708
1
    return PathDiagnosticLocation(
709
1
        BE->getBlock()->getTerminatorStmt()->getBeginLoc(), SMng);
710
1
  } else if (Optional<FunctionExitPoint> FE = P.getAs<FunctionExitPoint>()) {
711
1
    return PathDiagnosticLocation(FE->getStmt(), SMng,
712
1
                                  FE->getLocationContext());
713
1
  } else {
714
0
    llvm_unreachable("Unexpected ProgramPoint");
715
0
  }
716
1.89k
717
1.89k
  return PathDiagnosticLocation(S, SMng, P.getLocationContext());
718
1.89k
}
719
720
PathDiagnosticLocation PathDiagnosticLocation::createSingleLocation(
721
39
                                           const PathDiagnosticLocation &PDL) {
722
39
  FullSourceLoc L = PDL.asLocation();
723
39
  return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
724
39
}
725
726
FullSourceLoc
727
  PathDiagnosticLocation::genLocation(SourceLocation L,
728
98.8k
                                      LocationOrAnalysisDeclContext LAC) const {
729
98.8k
  assert(isValid());
730
98.8k
  // Note that we want a 'switch' here so that the compiler can warn us in
731
98.8k
  // case we add more cases.
732
98.8k
  switch (K) {
733
16.0k
    case SingleLocK:
734
16.0k
    case RangeK:
735
16.0k
      break;
736
82.4k
    case StmtK:
737
82.4k
      // Defensive checking.
738
82.4k
      if (!S)
739
0
        break;
740
82.4k
      return FullSourceLoc(getValidSourceLocation(S, LAC),
741
82.4k
                           const_cast<SourceManager&>(*SM));
742
82.4k
    case DeclK:
743
296
      // Defensive checking.
744
296
      if (!D)
745
0
        break;
746
296
      return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
747
16.0k
  }
748
16.0k
749
16.0k
  return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
750
16.0k
}
751
752
PathDiagnosticRange
753
99.0k
  PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
754
99.0k
  assert(isValid());
755
99.0k
  // Note that we want a 'switch' here so that the compiler can warn us in
756
99.0k
  // case we add more cases.
757
99.0k
  switch (K) {
758
16.3k
    case SingleLocK:
759
16.3k
      return PathDiagnosticRange(SourceRange(Loc,Loc), true);
760
0
    case RangeK:
761
0
      break;
762
82.4k
    case StmtK: {
763
82.4k
      const Stmt *S = asStmt();
764
82.4k
      switch (S->getStmtClass()) {
765
74.9k
        default:
766
74.9k
          break;
767
5.48k
        case Stmt::DeclStmtClass: {
768
5.48k
          const auto *DS = cast<DeclStmt>(S);
769
5.48k
          if (DS->isSingleDecl()) {
770
5.46k
            // Should always be the case, but we'll be defensive.
771
5.46k
            return SourceRange(DS->getBeginLoc(),
772
5.46k
                               DS->getSingleDecl()->getLocation());
773
5.46k
          }
774
12
          break;
775
12
        }
776
12
          // FIXME: Provide better range information for different
777
12
          //  terminators.
778
2.10k
        case Stmt::IfStmtClass:
779
2.10k
        case Stmt::WhileStmtClass:
780
2.10k
        case Stmt::DoStmtClass:
781
2.10k
        case Stmt::ForStmtClass:
782
2.10k
        case Stmt::ChooseExprClass:
783
2.10k
        case Stmt::IndirectGotoStmtClass:
784
2.10k
        case Stmt::SwitchStmtClass:
785
2.10k
        case Stmt::BinaryConditionalOperatorClass:
786
2.10k
        case Stmt::ConditionalOperatorClass:
787
2.10k
        case Stmt::ObjCForCollectionStmtClass: {
788
2.10k
          SourceLocation L = getValidSourceLocation(S, LAC);
789
2.10k
          return SourceRange(L, L);
790
74.9k
        }
791
74.9k
      }
792
74.9k
      SourceRange R = S->getSourceRange();
793
74.9k
      if (R.isValid())
794
74.9k
        return R;
795
0
      break;
796
0
    }
797
296
    case DeclK:
798
296
      if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
799
1
        return MD->getSourceRange();
800
295
      if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
801
6
        if (Stmt *Body = FD->getBody())
802
6
          return Body->getSourceRange();
803
289
      }
804
289
      else {
805
289
        SourceLocation L = D->getLocation();
806
289
        return PathDiagnosticRange(SourceRange(L, L), true);
807
289
      }
808
0
  }
809
0
810
0
  return SourceRange(Loc, Loc);
811
0
}
812
813
37.1k
void PathDiagnosticLocation::flatten() {
814
37.1k
  if (K == StmtK) {
815
29.3k
    K = RangeK;
816
29.3k
    S = nullptr;
817
29.3k
    D = nullptr;
818
29.3k
  }
819
7.73k
  else if (K == DeclK) {
820
432
    K = SingleLocK;
821
432
    S = nullptr;
822
432
    D = nullptr;
823
432
  }
824
37.1k
}
825
826
//===----------------------------------------------------------------------===//
827
// Manipulation of PathDiagnosticCallPieces.
828
//===----------------------------------------------------------------------===//
829
830
std::shared_ptr<PathDiagnosticCallPiece>
831
PathDiagnosticCallPiece::construct(const CallExitEnd &CE,
832
6.56k
                                   const SourceManager &SM) {
833
6.56k
  const Decl *caller = CE.getLocationContext()->getDecl();
834
6.56k
  PathDiagnosticLocation pos = getLocationForCaller(CE.getCalleeContext(),
835
6.56k
                                                    CE.getLocationContext(),
836
6.56k
                                                    SM);
837
6.56k
  return std::shared_ptr<PathDiagnosticCallPiece>(
838
6.56k
      new PathDiagnosticCallPiece(caller, pos));
839
6.56k
}
840
841
PathDiagnosticCallPiece *
842
PathDiagnosticCallPiece::construct(PathPieces &path,
843
166
                                   const Decl *caller) {
844
166
  std::shared_ptr<PathDiagnosticCallPiece> C(
845
166
      new PathDiagnosticCallPiece(path, caller));
846
166
  path.clear();
847
166
  auto *R = C.get();
848
166
  path.push_front(std::move(C));
849
166
  return R;
850
166
}
851
852
void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
853
6.72k
                                        const SourceManager &SM) {
854
6.72k
  const StackFrameContext *CalleeCtx = CE.getCalleeContext();
855
6.72k
  Callee = CalleeCtx->getDecl();
856
6.72k
857
6.72k
  callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
858
6.72k
  callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
859
6.72k
860
6.72k
  // Autosynthesized property accessors are special because we'd never
861
6.72k
  // pop back up to non-autosynthesized code until we leave them.
862
6.72k
  // This is not generally true for autosynthesized callees, which may call
863
6.72k
  // non-autosynthesized callbacks.
864
6.72k
  // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
865
6.72k
  // defaults to false.
866
6.72k
  if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
867
28
    IsCalleeAnAutosynthesizedPropertyAccessor = (
868
28
        MD->isPropertyAccessor() &&
869
28
        
CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized()3
);
870
6.72k
}
871
872
static void describeTemplateParameters(raw_ostream &Out,
873
                                       const ArrayRef<TemplateArgument> TAList,
874
                                       const LangOptions &LO,
875
                                       StringRef Prefix = StringRef(),
876
                                       StringRef Postfix = StringRef());
877
878
static void describeTemplateParameter(raw_ostream &Out,
879
                                      const TemplateArgument &TArg,
880
129
                                      const LangOptions &LO) {
881
129
882
129
  if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
883
34
    describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
884
95
  } else {
885
95
    TArg.print(PrintingPolicy(LO), Out);
886
95
  }
887
129
}
888
889
static void describeTemplateParameters(raw_ostream &Out,
890
                                       const ArrayRef<TemplateArgument> TAList,
891
                                       const LangOptions &LO,
892
91
                                       StringRef Prefix, StringRef Postfix) {
893
91
  if (TAList.empty())
894
26
    return;
895
65
896
65
  Out << Prefix;
897
129
  for (int I = 0, Last = TAList.size() - 1; I != Last; 
++I64
) {
898
64
    describeTemplateParameter(Out, TAList[I], LO);
899
64
    Out << ", ";
900
64
  }
901
65
  describeTemplateParameter(Out, TAList[TAList.size() - 1], LO);
902
65
  Out << Postfix;
903
65
}
904
905
static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
906
184
                          StringRef Prefix = StringRef()) {
907
184
  if (!D->getIdentifier())
908
0
    return;
909
184
  Out << Prefix << '\'' << *D;
910
184
  if (const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
911
17
    describeTemplateParameters(Out, T->getTemplateArgs().asArray(),
912
17
                               D->getASTContext().getLangOpts(), "<", ">");
913
184
914
184
  Out << '\'';
915
184
}
916
917
static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
918
                             bool ExtendedDescription,
919
1.71k
                             StringRef Prefix = StringRef()) {
920
1.71k
  if (!D)
921
0
    return false;
922
1.71k
923
1.71k
  if (isa<BlockDecl>(D)) {
924
113
    if (ExtendedDescription)
925
75
      Out << Prefix << "anonymous block";
926
113
    return ExtendedDescription;
927
113
  }
928
1.59k
929
1.59k
  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
930
358
    Out << Prefix;
931
358
    if (ExtendedDescription && 
!MD->isUserProvided()246
) {
932
36
      if (MD->isExplicitlyDefaulted())
933
10
        Out << "defaulted ";
934
26
      else
935
26
        Out << "implicit ";
936
36
    }
937
358
938
358
    if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
939
149
      if (CD->isDefaultConstructor())
940
24
        Out << "default ";
941
125
      else if (CD->isCopyConstructor())
942
20
        Out << "copy ";
943
105
      else if (CD->isMoveConstructor())
944
28
        Out << "move ";
945
149
946
149
      Out << "constructor";
947
149
      describeClass(Out, MD->getParent(), " for ");
948
209
    } else if (isa<CXXDestructorDecl>(MD)) {
949
59
      if (!MD->isUserProvided()) {
950
7
        Out << "destructor";
951
7
        describeClass(Out, MD->getParent(), " for ");
952
52
      } else {
953
52
        // Use ~Foo for explicitly-written destructors.
954
52
        Out << "'" << *MD << "'";
955
52
      }
956
150
    } else if (MD->isCopyAssignmentOperator()) {
957
14
        Out << "copy assignment operator";
958
14
        describeClass(Out, MD->getParent(), " for ");
959
136
    } else if (MD->isMoveAssignmentOperator()) {
960
14
        Out << "move assignment operator";
961
14
        describeClass(Out, MD->getParent(), " for ");
962
122
    } else {
963
122
      if (MD->getParent()->getIdentifier())
964
65
        Out << "'" << *MD->getParent() << "::" << *MD << "'";
965
57
      else
966
57
        Out << "'" << *MD << "'";
967
122
    }
968
358
969
358
    return true;
970
358
  }
971
1.24k
972
1.24k
  Out << Prefix << '\'' << cast<NamedDecl>(*D);
973
1.24k
974
1.24k
  // Adding template parameters.
975
1.24k
  if (const auto FD = dyn_cast<FunctionDecl>(D))
976
1.12k
    if (const TemplateArgumentList *TAList =
977
40
                                    FD->getTemplateSpecializationArgs())
978
40
      describeTemplateParameters(Out, TAList->asArray(),
979
40
                                 FD->getASTContext().getLangOpts(), "<", ">");
980
1.24k
981
1.24k
  Out << '\'';
982
1.24k
  return true;
983
1.24k
}
984
985
std::shared_ptr<PathDiagnosticEventPiece>
986
977
PathDiagnosticCallPiece::getCallEnterEvent() const {
987
977
  // We do not produce call enters and call exits for autosynthesized property
988
977
  // accessors. We do generally produce them for other functions coming from
989
977
  // the body farm because they may call callbacks that bring us back into
990
977
  // visible code.
991
977
  if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
992
5
    return nullptr;
993
972
994
972
  SmallString<256> buf;
995
972
  llvm::raw_svector_ostream Out(buf);
996
972
997
972
  Out << "Calling ";
998
972
  describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
999
972
1000
972
  assert(callEnter.asLocation().isValid());
1001
972
  return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
1002
972
}
1003
1004
std::shared_ptr<PathDiagnosticEventPiece>
1005
296
PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
1006
296
  if (!callEnterWithin.asLocation().isValid())
1007
0
    return nullptr;
1008
296
  if (Callee->isImplicit() || 
!Callee->hasBody()286
)
1009
20
    return nullptr;
1010
276
  if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
1011
48
    if (MD->isDefaulted())
1012
4
      return nullptr;
1013
272
1014
272
  SmallString<256> buf;
1015
272
  llvm::raw_svector_ostream Out(buf);
1016
272
1017
272
  Out << "Entered call";
1018
272
  describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
1019
272
1020
272
  return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
1021
272
}
1022
1023
std::shared_ptr<PathDiagnosticEventPiece>
1024
829
PathDiagnosticCallPiece::getCallExitEvent() const {
1025
829
  // We do not produce call enters and call exits for autosynthesized property
1026
829
  // accessors. We do generally produce them for other functions coming from
1027
829
  // the body farm because they may call callbacks that bring us back into
1028
829
  // visible code.
1029
829
  if (NoExit || 
IsCalleeAnAutosynthesizedPropertyAccessor506
)
1030
327
    return nullptr;
1031
502
1032
502
  SmallString<256> buf;
1033
502
  llvm::raw_svector_ostream Out(buf);
1034
502
1035
502
  if (!CallStackMessage.empty()) {
1036
34
    Out << CallStackMessage;
1037
468
  } else {
1038
468
    bool DidDescribe = describeCodeDecl(Out, Callee,
1039
468
                                        /*ExtendedDescription=*/false,
1040
468
                                        "Returning from ");
1041
468
    if (!DidDescribe)
1042
34
      Out << "Returning to caller";
1043
468
  }
1044
502
1045
502
  assert(callReturn.asLocation().isValid());
1046
502
  return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
1047
502
}
1048
1049
138
static void compute_path_size(const PathPieces &pieces, unsigned &size) {
1050
188
  for (const auto &I : pieces) {
1051
188
    const PathDiagnosticPiece *piece = I.get();
1052
188
    if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
1053
12
      compute_path_size(cp->path, size);
1054
176
    else
1055
176
      ++size;
1056
188
  }
1057
138
}
1058
1059
126
unsigned PathDiagnostic::full_size() {
1060
126
  unsigned size = 0;
1061
126
  compute_path_size(path, size);
1062
126
  return size;
1063
126
}
1064
1065
//===----------------------------------------------------------------------===//
1066
// FoldingSet profiling methods.
1067
//===----------------------------------------------------------------------===//
1068
1069
50.7k
void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
1070
50.7k
  ID.AddInteger(Range.getBegin().getRawEncoding());
1071
50.7k
  ID.AddInteger(Range.getEnd().getRawEncoding());
1072
50.7k
  ID.AddInteger(Loc.getRawEncoding());
1073
50.7k
}
1074
1075
2.74k
void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1076
2.74k
  ID.AddInteger((unsigned) getKind());
1077
2.74k
  ID.AddString(str);
1078
2.74k
  // FIXME: Add profiling support for code hints.
1079
2.74k
  ID.AddInteger((unsigned) getDisplayHint());
1080
2.74k
  ArrayRef<SourceRange> Ranges = getRanges();
1081
2.74k
  for (const auto &I : Ranges) {
1082
2.74k
    ID.AddInteger(I.getBegin().getRawEncoding());
1083
2.74k
    ID.AddInteger(I.getEnd().getRawEncoding());
1084
2.74k
  }
1085
2.74k
}
1086
1087
0
void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1088
0
  PathDiagnosticPiece::Profile(ID);
1089
0
  for (const auto &I : path)
1090
0
    ID.Add(*I);
1091
0
}
1092
1093
2.74k
void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1094
2.74k
  PathDiagnosticPiece::Profile(ID);
1095
2.74k
  ID.Add(Pos);
1096
2.74k
}
1097
1098
0
void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1099
0
  PathDiagnosticPiece::Profile(ID);
1100
0
  for (const auto &I : *this)
1101
0
    ID.Add(I);
1102
0
}
1103
1104
0
void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1105
0
  PathDiagnosticSpotPiece::Profile(ID);
1106
0
  for (const auto &I : subPieces)
1107
0
    ID.Add(*I);
1108
0
}
1109
1110
0
void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
1111
0
  PathDiagnosticSpotPiece::Profile(ID);
1112
0
}
1113
1114
149
void PathDiagnosticPopUpPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1115
149
  PathDiagnosticSpotPiece::Profile(ID);
1116
149
}
1117
1118
45.5k
void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
1119
45.5k
  ID.Add(getLocation());
1120
45.5k
  ID.AddString(BugType);
1121
45.5k
  ID.AddString(VerboseDesc);
1122
45.5k
  ID.AddString(Category);
1123
45.5k
}
1124
1125
0
void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1126
0
  Profile(ID);
1127
0
  for (const auto &I : path)
1128
0
    ID.Add(*I);
1129
0
  for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1130
0
    ID.AddString(*I);
1131
0
}
1132
1133
0
LLVM_DUMP_METHOD void PathPieces::dump() const {
1134
0
  unsigned index = 0;
1135
0
  for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
1136
0
    llvm::errs() << "[" << index++ << "]  ";
1137
0
    (*I)->dump();
1138
0
    llvm::errs() << "\n";
1139
0
  }
1140
0
}
1141
1142
0
LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const {
1143
0
  llvm::errs() << "CALL\n--------------\n";
1144
0
1145
0
  if (const Stmt *SLoc = getLocation().getStmtOrNull())
1146
0
    SLoc->dump();
1147
0
  else if (const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee()))
1148
0
    llvm::errs() << *ND << "\n";
1149
0
  else
1150
0
    getLocation().dump();
1151
0
}
1152
1153
0
LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const {
1154
0
  llvm::errs() << "EVENT\n--------------\n";
1155
0
  llvm::errs() << getString() << "\n";
1156
0
  llvm::errs() << " ---- at ----\n";
1157
0
  getLocation().dump();
1158
0
}
1159
1160
0
LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const {
1161
0
  llvm::errs() << "CONTROL\n--------------\n";
1162
0
  getStartLocation().dump();
1163
0
  llvm::errs() << " ---- to ----\n";
1164
0
  getEndLocation().dump();
1165
0
}
1166
1167
0
LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
1168
0
  llvm::errs() << "MACRO\n--------------\n";
1169
0
  // FIXME: Print which macro is being invoked.
1170
0
}
1171
1172
0
LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const {
1173
0
  llvm::errs() << "NOTE\n--------------\n";
1174
0
  llvm::errs() << getString() << "\n";
1175
0
  llvm::errs() << " ---- at ----\n";
1176
0
  getLocation().dump();
1177
0
}
1178
1179
0
LLVM_DUMP_METHOD void PathDiagnosticPopUpPiece::dump() const {
1180
0
  llvm::errs() << "POP-UP\n--------------\n";
1181
0
  llvm::errs() << getString() << "\n";
1182
0
  llvm::errs() << " ---- at ----\n";
1183
0
  getLocation().dump();
1184
0
}
1185
1186
0
LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const {
1187
0
  if (!isValid()) {
1188
0
    llvm::errs() << "<INVALID>\n";
1189
0
    return;
1190
0
  }
1191
0
1192
0
  switch (K) {
1193
0
  case RangeK:
1194
0
    // FIXME: actually print the range.
1195
0
    llvm::errs() << "<range>\n";
1196
0
    break;
1197
0
  case SingleLocK:
1198
0
    asLocation().dump();
1199
0
    llvm::errs() << "\n";
1200
0
    break;
1201
0
  case StmtK:
1202
0
    if (S)
1203
0
      S->dump();
1204
0
    else
1205
0
      llvm::errs() << "<NULL STMT>\n";
1206
0
    break;
1207
0
  case DeclK:
1208
0
    if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
1209
0
      llvm::errs() << *ND << "\n";
1210
0
    else if (isa<BlockDecl>(D))
1211
0
      // FIXME: Make this nicer.
1212
0
      llvm::errs() << "<block>\n";
1213
0
    else if (D)
1214
0
      llvm::errs() << "<unknown decl>\n";
1215
0
    else
1216
0
      llvm::errs() << "<NULL DECL>\n";
1217
0
    break;
1218
0
  }
1219
0
}