Coverage Report

Created: 2020-09-22 08:39

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