Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/StaticAnalyzer/Core/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/StaticAnalyzer/Core/BugReporter/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 "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
33
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
34
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
35
#include "llvm/ADT/ArrayRef.h"
36
#include "llvm/ADT/FoldingSet.h"
37
#include "llvm/ADT/None.h"
38
#include "llvm/ADT/Optional.h"
39
#include "llvm/ADT/STLExtras.h"
40
#include "llvm/ADT/SmallString.h"
41
#include "llvm/ADT/SmallVector.h"
42
#include "llvm/ADT/StringExtras.h"
43
#include "llvm/ADT/StringRef.h"
44
#include "llvm/Support/Casting.h"
45
#include "llvm/Support/ErrorHandling.h"
46
#include "llvm/Support/raw_ostream.h"
47
#include <cassert>
48
#include <cstring>
49
#include <memory>
50
#include <utility>
51
#include <vector>
52
53
using namespace clang;
54
using namespace ento;
55
56
0
bool PathDiagnosticMacroPiece::containsEvent() const {
57
0
  for (const auto &P : subPieces) {
58
0
    if (isa<PathDiagnosticEventPiece>(*P))
59
0
      return true;
60
0
    if (const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(P.get()))
61
0
      if (MP->containsEvent())
62
0
        return true;
63
0
  }
64
0
  return false;
65
0
}
66
67
69.9k
static StringRef StripTrailingDots(StringRef s) {
68
71.0k
  for (StringRef::size_type i = s.size(); i != 0; 
--i1.10k
)
69
59.3k
    if (s[i - 1] != '.')
70
58.2k
      return s.substr(0, i);
71
69.9k
  
return {}11.6k
;
72
69.9k
}
73
74
PathDiagnosticPiece::PathDiagnosticPiece(StringRef s,
75
                                         Kind k, DisplayHint hint)
76
23.1k
    : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
77
78
PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
79
19.2k
    : kind(k), Hint(hint) {}
80
81
42.3k
PathDiagnosticPiece::~PathDiagnosticPiece() = default;
82
83
21.5k
PathDiagnosticEventPiece::~PathDiagnosticEventPiece() = default;
84
85
6.89k
PathDiagnosticCallPiece::~PathDiagnosticCallPiece() = default;
86
87
12.9k
PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() = default;
88
89
31
PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() = default;
90
91
166
PathDiagnosticNotePiece::~PathDiagnosticNotePiece() = default;
92
93
836
PathDiagnosticPopUpPiece::~PathDiagnosticPopUpPiece() = default;
94
95
void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
96
13.3k
                           bool ShouldFlattenMacros) const {
97
20.5k
  for (auto &Piece : *this) {
98
20.5k
    switch (Piece->getKind()) {
99
20.5k
    case PathDiagnosticPiece::Call: {
100
678
      auto &Call = cast<PathDiagnosticCallPiece>(*Piece);
101
678
      if (auto CallEnter = Call.getCallEnterEvent())
102
675
        Current.push_back(std::move(CallEnter));
103
678
      Call.path.flattenTo(Primary, Primary, ShouldFlattenMacros);
104
678
      if (auto callExit = Call.getCallExitEvent())
105
375
        Current.push_back(std::move(callExit));
106
678
      break;
107
20.5k
    }
108
20.5k
    case PathDiagnosticPiece::Macro: {
109
31
      auto &Macro = cast<PathDiagnosticMacroPiece>(*Piece);
110
31
      if (ShouldFlattenMacros) {
111
31
        Macro.subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
112
31
      } else {
113
0
        Current.push_back(Piece);
114
0
        PathPieces NewPath;
115
0
        Macro.subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
116
0
        // FIXME: This probably shouldn't mutate the original path piece.
117
0
        Macro.subPieces = NewPath;
118
0
      }
119
31
      break;
120
20.5k
    }
121
20.5k
    case PathDiagnosticPiece::Event:
122
19.8k
    case PathDiagnosticPiece::ControlFlow:
123
19.8k
    case PathDiagnosticPiece::Note:
124
19.8k
    case PathDiagnosticPiece::PopUp:
125
19.8k
      Current.push_back(Piece);
126
19.8k
      break;
127
20.5k
    }
128
20.5k
  }
129
13.3k
}
130
131
11.6k
PathDiagnostic::~PathDiagnostic() = default;
132
133
PathDiagnostic::PathDiagnostic(
134
    StringRef CheckName, const Decl *declWithIssue, StringRef bugtype,
135
    StringRef verboseDesc, StringRef shortDesc, StringRef category,
136
    PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique,
137
    std::unique_ptr<FilesToLineNumsMap> ExecutedLines)
138
    : CheckName(CheckName), DeclWithIssue(declWithIssue),
139
      BugType(StripTrailingDots(bugtype)),
140
      VerboseDesc(StripTrailingDots(verboseDesc)),
141
      ShortDesc(StripTrailingDots(shortDesc)),
142
      Category(StripTrailingDots(category)), UniqueingLoc(LocationToUnique),
143
      UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)),
144
11.6k
      path(pathImpl) {}
145
146
static PathDiagnosticCallPiece *
147
getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP,
148
9
                                const SourceManager &SMgr) {
149
9
  SourceLocation CallLoc = CP->callEnter.asLocation();
150
9
151
9
  // If the call is within a macro, don't do anything (for now).
152
9
  if (CallLoc.isMacroID())
153
3
    return nullptr;
154
6
155
6
  assert(AnalysisManager::isInCodeFile(CallLoc, SMgr) &&
156
6
         "The call piece should not be in a header file.");
157
6
158
6
  // Check if CP represents a path through a function outside of the main file.
159
6
  if (!AnalysisManager::isInCodeFile(CP->callEnterWithin.asLocation(), SMgr))
160
2
    return CP;
161
4
162
4
  const PathPieces &Path = CP->path;
163
4
  if (Path.empty())
164
0
    return nullptr;
165
4
166
4
  // Check if the last piece in the callee path is a call to a function outside
167
4
  // of the main file.
168
4
  if (auto *CPInner = dyn_cast<PathDiagnosticCallPiece>(Path.back().get()))
169
2
    return getFirstStackedCallToHeaderFile(CPInner, SMgr);
170
2
171
2
  // Otherwise, the last piece is in the main file.
172
2
  return nullptr;
173
2
}
174
175
14
void PathDiagnostic::resetDiagnosticLocationToMainFile() {
176
14
  if (path.empty())
177
7
    return;
178
7
179
7
  PathDiagnosticPiece *LastP = path.back().get();
180
7
  assert(LastP);
181
7
  const SourceManager &SMgr = LastP->getLocation().getManager();
182
7
183
7
  // We only need to check if the report ends inside headers, if the last piece
184
7
  // is a call piece.
185
7
  if (auto *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
186
7
    CP = getFirstStackedCallToHeaderFile(CP, SMgr);
187
7
    if (CP) {
188
2
      // Mark the piece.
189
2
       CP->setAsLastInMainSourceFile();
190
2
191
2
      // Update the path diagnostic message.
192
2
      const auto *ND = dyn_cast<NamedDecl>(CP->getCallee());
193
2
      if (ND) {
194
2
        SmallString<200> buf;
195
2
        llvm::raw_svector_ostream os(buf);
196
2
        os << " (within a call to '" << ND->getDeclName() << "')";
197
2
        appendToDesc(os.str());
198
2
      }
199
2
200
2
      // Reset the report containing declaration and location.
201
2
      DeclWithIssue = CP->getCaller();
202
2
      Loc = CP->getLocation();
203
2
204
2
      return;
205
2
    }
206
7
  }
207
7
}
208
209
0
void PathDiagnosticConsumer::anchor() {}
210
211
997
PathDiagnosticConsumer::~PathDiagnosticConsumer() {
212
997
  // Delete the contents of the FoldingSet if it isn't empty already.
213
997
  for (auto &Diag : Diags)
214
0
    delete &Diag;
215
997
}
216
217
void PathDiagnosticConsumer::HandlePathDiagnostic(
218
11.6k
    std::unique_ptr<PathDiagnostic> D) {
219
11.6k
  if (!D || D->path.empty())
220
0
    return;
221
11.6k
222
11.6k
  // We need to flatten the locations (convert Stmt* to locations) because
223
11.6k
  // the referenced statements may be freed by the time the diagnostics
224
11.6k
  // are emitted.
225
11.6k
  D->flattenLocations();
226
11.6k
227
11.6k
  // If the PathDiagnosticConsumer does not support diagnostics that
228
11.6k
  // cross file boundaries, prune out such diagnostics now.
229
11.6k
  if (!supportsCrossFileDiagnostics()) {
230
469
    // Verify that the entire path is from the same FileID.
231
469
    FileID FID;
232
469
    const SourceManager &SMgr = D->path.front()->getLocation().getManager();
233
469
    SmallVector<const PathPieces *, 5> WorkList;
234
469
    WorkList.push_back(&D->path);
235
469
    SmallString<128> buf;
236
469
    llvm::raw_svector_ostream warning(buf);
237
469
    warning << "warning: Path diagnostic report is not generated. Current "
238
469
            << "output format does not support diagnostics that cross file "
239
469
            << "boundaries. Refer to --analyzer-output for valid output "
240
469
            << "formats\n";
241
469
242
1.04k
    while (!WorkList.empty()) {
243
576
      const PathPieces &path = *WorkList.pop_back_val();
244
576
245
3.11k
      for (const auto &I : path) {
246
3.11k
        const PathDiagnosticPiece *piece = I.get();
247
3.11k
        FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc();
248
3.11k
249
3.11k
        if (FID.isInvalid()) {
250
469
          FID = SMgr.getFileID(L);
251
2.64k
        } else if (SMgr.getFileID(L) != FID) {
252
1
          llvm::errs() << warning.str();
253
1
          return;
254
1
        }
255
3.11k
256
3.11k
        // Check the source ranges.
257
3.11k
        ArrayRef<SourceRange> Ranges = piece->getRanges();
258
3.11k
        for (const auto &I : Ranges) {
259
1.28k
          SourceLocation L = SMgr.getExpansionLoc(I.getBegin());
260
1.28k
          if (!L.isFileID() || SMgr.getFileID(L) != FID) {
261
0
            llvm::errs() << warning.str();
262
0
            return;
263
0
          }
264
1.28k
          L = SMgr.getExpansionLoc(I.getEnd());
265
1.28k
          if (!L.isFileID() || SMgr.getFileID(L) != FID) {
266
0
            llvm::errs() << warning.str();
267
0
            return;
268
0
          }
269
1.28k
        }
270
3.11k
271
3.11k
        if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece))
272
76
          WorkList.push_back(&call->path);
273
3.03k
        else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece))
274
31
          WorkList.push_back(&macro->subPieces);
275
3.11k
      }
276
576
    }
277
469
278
469
    
if (468
FID.isInvalid()468
)
279
0
      return; // FIXME: Emit a warning?
280
11.6k
  }
281
11.6k
282
11.6k
  // Profile the node to see if we already have something matching it
283
11.6k
  llvm::FoldingSetNodeID profile;
284
11.6k
  D->Profile(profile);
285
11.6k
  void *InsertPos = nullptr;
286
11.6k
287
11.6k
  if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
288
64
    // Keep the PathDiagnostic with the shorter path.
289
64
    // Note, the enclosing routine is called in deterministic order, so the
290
64
    // results will be consistent between runs (no reason to break ties if the
291
64
    // size is the same).
292
64
    const unsigned orig_size = orig->full_size();
293
64
    const unsigned new_size = D->full_size();
294
64
    if (orig_size <= new_size)
295
64
      return;
296
0
297
0
    assert(orig != D.get());
298
0
    Diags.RemoveNode(orig);
299
0
    delete orig;
300
0
  }
301
11.6k
302
11.6k
  Diags.InsertNode(D.release());
303
11.6k
}
304
305
static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y);
306
307
static Optional<bool>
308
compareControlFlow(const PathDiagnosticControlFlowPiece &X,
309
0
                   const PathDiagnosticControlFlowPiece &Y) {
310
0
  FullSourceLoc XSL = X.getStartLocation().asLocation();
311
0
  FullSourceLoc YSL = Y.getStartLocation().asLocation();
312
0
  if (XSL != YSL)
313
0
    return XSL.isBeforeInTranslationUnitThan(YSL);
314
0
  FullSourceLoc XEL = X.getEndLocation().asLocation();
315
0
  FullSourceLoc YEL = Y.getEndLocation().asLocation();
316
0
  if (XEL != YEL)
317
0
    return XEL.isBeforeInTranslationUnitThan(YEL);
318
0
  return None;
319
0
}
320
321
static Optional<bool> compareMacro(const PathDiagnosticMacroPiece &X,
322
0
                                   const PathDiagnosticMacroPiece &Y) {
323
0
  return comparePath(X.subPieces, Y.subPieces);
324
0
}
325
326
static Optional<bool> compareCall(const PathDiagnosticCallPiece &X,
327
0
                                  const PathDiagnosticCallPiece &Y) {
328
0
  FullSourceLoc X_CEL = X.callEnter.asLocation();
329
0
  FullSourceLoc Y_CEL = Y.callEnter.asLocation();
330
0
  if (X_CEL != Y_CEL)
331
0
    return X_CEL.isBeforeInTranslationUnitThan(Y_CEL);
332
0
  FullSourceLoc X_CEWL = X.callEnterWithin.asLocation();
333
0
  FullSourceLoc Y_CEWL = Y.callEnterWithin.asLocation();
334
0
  if (X_CEWL != Y_CEWL)
335
0
    return X_CEWL.isBeforeInTranslationUnitThan(Y_CEWL);
336
0
  FullSourceLoc X_CRL = X.callReturn.asLocation();
337
0
  FullSourceLoc Y_CRL = Y.callReturn.asLocation();
338
0
  if (X_CRL != Y_CRL)
339
0
    return X_CRL.isBeforeInTranslationUnitThan(Y_CRL);
340
0
  return comparePath(X.path, Y.path);
341
0
}
342
343
static Optional<bool> comparePiece(const PathDiagnosticPiece &X,
344
5
                                   const PathDiagnosticPiece &Y) {
345
5
  if (X.getKind() != Y.getKind())
346
0
    return X.getKind() < Y.getKind();
347
5
348
5
  FullSourceLoc XL = X.getLocation().asLocation();
349
5
  FullSourceLoc YL = Y.getLocation().asLocation();
350
5
  if (XL != YL)
351
0
    return XL.isBeforeInTranslationUnitThan(YL);
352
5
353
5
  if (X.getString() != Y.getString())
354
0
    return X.getString() < Y.getString();
355
5
356
5
  if (X.getRanges().size() != Y.getRanges().size())
357
1
    return X.getRanges().size() < Y.getRanges().size();
358
4
359
4
  const SourceManager &SM = XL.getManager();
360
4
361
4
  for (unsigned i = 0, n = X.getRanges().size(); i < n; 
++i0
) {
362
4
    SourceRange XR = X.getRanges()[i];
363
4
    SourceRange YR = Y.getRanges()[i];
364
4
    if (XR != YR) {
365
4
      if (XR.getBegin() != YR.getBegin())
366
0
        return SM.isBeforeInTranslationUnit(XR.getBegin(), YR.getBegin());
367
4
      return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd());
368
4
    }
369
4
  }
370
4
371
4
  switch (X.getKind()) {
372
0
    case PathDiagnosticPiece::ControlFlow:
373
0
      return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X),
374
0
                                cast<PathDiagnosticControlFlowPiece>(Y));
375
0
    case PathDiagnosticPiece::Macro:
376
0
      return compareMacro(cast<PathDiagnosticMacroPiece>(X),
377
0
                          cast<PathDiagnosticMacroPiece>(Y));
378
0
    case PathDiagnosticPiece::Call:
379
0
      return compareCall(cast<PathDiagnosticCallPiece>(X),
380
0
                         cast<PathDiagnosticCallPiece>(Y));
381
0
    case PathDiagnosticPiece::Event:
382
0
    case PathDiagnosticPiece::Note:
383
0
    case PathDiagnosticPiece::PopUp:
384
0
      return None;
385
0
  }
386
0
  llvm_unreachable("all cases handled");
387
0
}
388
389
6
static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) {
390
6
  if (X.size() != Y.size())
391
1
    return X.size() < Y.size();
392
5
393
5
  PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
394
5
  PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
395
5
396
5
  for ( ; X_I != X_end && Y_I != Y_end; 
++X_I, ++Y_I0
) {
397
5
    Optional<bool> b = comparePiece(**X_I, **Y_I);
398
5
    if (b.hasValue())
399
5
      return b.getValue();
400
5
  }
401
5
402
5
  
return None0
;
403
5
}
404
405
57.8k
static bool compareCrossTUSourceLocs(FullSourceLoc XL, FullSourceLoc YL) {
406
57.8k
  std::pair<FileID, unsigned> XOffs = XL.getDecomposedLoc();
407
57.8k
  std::pair<FileID, unsigned> YOffs = YL.getDecomposedLoc();
408
57.8k
  const SourceManager &SM = XL.getManager();
409
57.8k
  std::pair<bool, bool> InSameTU = SM.isInTheSameTranslationUnit(XOffs, YOffs);
410
57.8k
  if (InSameTU.first)
411
57.8k
    return XL.isBeforeInTranslationUnitThan(YL);
412
21
  const FileEntry *XFE = SM.getFileEntryForID(XL.getSpellingLoc().getFileID());
413
21
  const FileEntry *YFE = SM.getFileEntryForID(YL.getSpellingLoc().getFileID());
414
21
  if (!XFE || !YFE)
415
0
    return XFE && !YFE;
416
21
  int NameCmp = XFE->getName().compare(YFE->getName());
417
21
  if (NameCmp != 0)
418
21
    return NameCmp == -1;
419
0
  // Last resort: Compare raw file IDs that are possibly expansions.
420
0
  return XL.getFileID() < YL.getFileID();
421
0
}
422
423
57.9k
static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
424
57.9k
  FullSourceLoc XL = X.getLocation().asLocation();
425
57.9k
  FullSourceLoc YL = Y.getLocation().asLocation();
426
57.9k
  if (XL != YL)
427
57.8k
    return compareCrossTUSourceLocs(XL, YL);
428
124
  if (X.getBugType() != Y.getBugType())
429
28
    return X.getBugType() < Y.getBugType();
430
96
  if (X.getCategory() != Y.getCategory())
431
0
    return X.getCategory() < Y.getCategory();
432
96
  if (X.getVerboseDescription() != Y.getVerboseDescription())
433
90
    return X.getVerboseDescription() < Y.getVerboseDescription();
434
6
  if (X.getShortDescription() != Y.getShortDescription())
435
0
    return X.getShortDescription() < Y.getShortDescription();
436
6
  if (X.getDeclWithIssue() != Y.getDeclWithIssue()) {
437
0
    const Decl *XD = X.getDeclWithIssue();
438
0
    if (!XD)
439
0
      return true;
440
0
    const Decl *YD = Y.getDeclWithIssue();
441
0
    if (!YD)
442
0
      return false;
443
0
    SourceLocation XDL = XD->getLocation();
444
0
    SourceLocation YDL = YD->getLocation();
445
0
    if (XDL != YDL) {
446
0
      const SourceManager &SM = XL.getManager();
447
0
      return compareCrossTUSourceLocs(FullSourceLoc(XDL, SM),
448
0
                                      FullSourceLoc(YDL, SM));
449
0
    }
450
6
  }
451
6
  PathDiagnostic::meta_iterator XI = X.meta_begin(), XE = X.meta_end();
452
6
  PathDiagnostic::meta_iterator YI = Y.meta_begin(), YE = Y.meta_end();
453
6
  if (XE - XI != YE - YI)
454
0
    return (XE - XI) < (YE - YI);
455
6
  for ( ; XI != XE ; 
++XI, ++YI0
) {
456
0
    if (*XI != *YI)
457
0
      return (*XI) < (*YI);
458
0
  }
459
6
  Optional<bool> b = comparePath(X.path, Y.path);
460
6
  assert(b.hasValue());
461
6
  return b.getValue();
462
6
}
463
464
void PathDiagnosticConsumer::FlushDiagnostics(
465
1.02k
                                     PathDiagnosticConsumer::FilesMade *Files) {
466
1.02k
  if (flushed)
467
30
    return;
468
997
469
997
  flushed = true;
470
997
471
997
  std::vector<const PathDiagnostic *> BatchDiags;
472
997
  for (const auto &D : Diags)
473
11.6k
    BatchDiags.push_back(&D);
474
997
475
997
  // Sort the diagnostics so that they are always emitted in a deterministic
476
997
  // order.
477
997
  int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
478
57.9k
      [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
479
57.9k
        assert(*X != *Y && "PathDiagnostics not uniqued!");
480
57.9k
        if (compare(**X, **Y))
481
26.7k
          return -1;
482
31.2k
        assert(compare(**Y, **X) && "Not a total order!");
483
31.2k
        return 1;
484
31.2k
      };
485
997
  array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
486
997
487
997
  FlushDiagnosticsImpl(BatchDiags, Files);
488
997
489
997
  // Delete the flushed diagnostics.
490
997
  for (const auto D : BatchDiags)
491
11.6k
    delete D;
492
997
493
997
  // Clear out the FoldingSet.
494
997
  Diags.clear();
495
997
}
496
497
918
PathDiagnosticConsumer::FilesMade::~FilesMade() {
498
918
  for (PDFileEntry &Entry : Set)
499
78
    Entry.~PDFileEntry();
500
918
}
501
502
void PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD,
503
                                                      StringRef ConsumerName,
504
78
                                                      StringRef FileName) {
505
78
  llvm::FoldingSetNodeID NodeID;
506
78
  NodeID.Add(PD);
507
78
  void *InsertPos;
508
78
  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
509
78
  if (!Entry) {
510
78
    Entry = Alloc.Allocate<PDFileEntry>();
511
78
    Entry = new (Entry) PDFileEntry(NodeID);
512
78
    Set.InsertNode(Entry, InsertPos);
513
78
  }
514
78
515
78
  // Allocate persistent storage for the file name.
516
78
  char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
517
78
  memcpy(FileName_cstr, FileName.data(), FileName.size());
518
78
519
78
  Entry->files.push_back(std::make_pair(ConsumerName,
520
78
                                        StringRef(FileName_cstr,
521
78
                                                  FileName.size())));
522
78
}
523
524
PathDiagnosticConsumer::PDFileEntry::ConsumerFiles *
525
1
PathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) {
526
1
  llvm::FoldingSetNodeID NodeID;
527
1
  NodeID.Add(PD);
528
1
  void *InsertPos;
529
1
  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
530
1
  if (!Entry)
531
0
    return nullptr;
532
1
  return &Entry->files;
533
1
}
534
535
//===----------------------------------------------------------------------===//
536
// PathDiagnosticLocation methods.
537
//===----------------------------------------------------------------------===//
538
539
static SourceLocation getValidSourceLocation(const Stmt* S,
540
                                             LocationOrAnalysisDeclContext LAC,
541
79.8k
                                             bool UseEnd = false) {
542
79.8k
  SourceLocation L = UseEnd ? 
S->getEndLoc()5
:
S->getBeginLoc()79.8k
;
543
79.8k
  assert(!LAC.isNull() && "A valid LocationContext or AnalysisDeclContext should "
544
79.8k
                          "be passed to PathDiagnosticLocation upon creation.");
545
79.8k
546
79.8k
  // S might be a temporary statement that does not have a location in the
547
79.8k
  // source code, so find an enclosing statement and use its location.
548
79.8k
  if (!L.isValid()) {
549
49
    AnalysisDeclContext *ADC;
550
49
    if (LAC.is<const LocationContext*>())
551
49
      ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext();
552
0
    else
553
0
      ADC = LAC.get<AnalysisDeclContext*>();
554
49
555
49
    ParentMap &PM = ADC->getParentMap();
556
49
557
49
    const Stmt *Parent = S;
558
51
    do {
559
51
      Parent = PM.getParent(Parent);
560
51
561
51
      // In rare cases, we have implicit top-level expressions,
562
51
      // such as arguments for implicit member initializers.
563
51
      // In this case, fall back to the start of the body (even if we were
564
51
      // asked for the statement end location).
565
51
      if (!Parent) {
566
47
        const Stmt *Body = ADC->getBody();
567
47
        if (Body)
568
47
          L = Body->getBeginLoc();
569
0
        else
570
0
          L = ADC->getDecl()->getEndLoc();
571
47
        break;
572
47
      }
573
4
574
4
      L = UseEnd ? 
Parent->getEndLoc()0
: Parent->getBeginLoc();
575
4
    } while (!L.isValid());
576
49
  }
577
79.8k
578
79.8k
  // FIXME: Ironically, this assert actually fails in some cases.
579
79.8k
  //assert(L.isValid());
580
79.8k
  return L;
581
79.8k
}
582
583
static PathDiagnosticLocation
584
getLocationForCaller(const StackFrameContext *SFC,
585
                     const LocationContext *CallerCtx,
586
13.6k
                     const SourceManager &SM) {
587
13.6k
  const CFGBlock &Block = *SFC->getCallSiteBlock();
588
13.6k
  CFGElement Source = Block[SFC->getIndex()];
589
13.6k
590
13.6k
  switch (Source.getKind()) {
591
13.6k
  case CFGElement::Statement:
592
13.5k
  case CFGElement::Constructor:
593
13.5k
  case CFGElement::CXXRecordTypedCall:
594
13.5k
    return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
595
13.5k
                                  SM, CallerCtx);
596
13.5k
  case CFGElement::Initializer: {
597
0
    const CFGInitializer &Init = Source.castAs<CFGInitializer>();
598
0
    return PathDiagnosticLocation(Init.getInitializer()->getInit(),
599
0
                                  SM, CallerCtx);
600
13.5k
  }
601
13.5k
  case CFGElement::AutomaticObjectDtor: {
602
15
    const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
603
15
    return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(),
604
15
                                             SM, CallerCtx);
605
13.5k
  }
606
13.5k
  case CFGElement::DeleteDtor: {
607
24
    const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
608
24
    return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
609
13.5k
  }
610
13.5k
  case CFGElement::BaseDtor:
611
4
  case CFGElement::MemberDtor: {
612
4
    const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
613
4
    if (const Stmt *CallerBody = CallerInfo->getBody())
614
4
      return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
615
0
    return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
616
0
  }
617
2
  case CFGElement::NewAllocator: {
618
2
    const CFGNewAllocator &Alloc = Source.castAs<CFGNewAllocator>();
619
2
    return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerCtx);
620
0
  }
621
3
  case CFGElement::TemporaryDtor: {
622
3
    // Temporary destructors are for temporaries. They die immediately at around
623
3
    // the location of CXXBindTemporaryExpr. If they are lifetime-extended,
624
3
    // they'd be dealt with via an AutomaticObjectDtor instead.
625
3
    const auto &Dtor = Source.castAs<CFGTemporaryDtor>();
626
3
    return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM,
627
3
                                             CallerCtx);
628
0
  }
629
0
  case CFGElement::ScopeBegin:
630
0
  case CFGElement::ScopeEnd:
631
0
    llvm_unreachable("not yet implemented!");
632
0
  case CFGElement::LifetimeEnds:
633
0
  case CFGElement::LoopExit:
634
0
    llvm_unreachable("CFGElement kind should not be on callsite!");
635
0
  }
636
0
637
0
  llvm_unreachable("Unknown CFGElement kind");
638
0
}
639
640
PathDiagnosticLocation
641
PathDiagnosticLocation::createBegin(const Decl *D,
642
8.37k
                                    const SourceManager &SM) {
643
8.37k
  return PathDiagnosticLocation(D->getBeginLoc(), SM, SingleLocK);
644
8.37k
}
645
646
PathDiagnosticLocation
647
PathDiagnosticLocation::createBegin(const Stmt *S,
648
                                    const SourceManager &SM,
649
2.78k
                                    LocationOrAnalysisDeclContext LAC) {
650
2.78k
  return PathDiagnosticLocation(getValidSourceLocation(S, LAC),
651
2.78k
                                SM, SingleLocK);
652
2.78k
}
653
654
PathDiagnosticLocation
655
PathDiagnosticLocation::createEnd(const Stmt *S,
656
                                  const SourceManager &SM,
657
723
                                  LocationOrAnalysisDeclContext LAC) {
658
723
  if (const auto *CS = dyn_cast<CompoundStmt>(S))
659
718
    return createEndBrace(CS, SM);
660
5
  return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
661
5
                                SM, SingleLocK);
662
5
}
663
664
PathDiagnosticLocation
665
PathDiagnosticLocation::createOperatorLoc(const BinaryOperator *BO,
666
3.02k
                                          const SourceManager &SM) {
667
3.02k
  return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
668
3.02k
}
669
670
PathDiagnosticLocation
671
PathDiagnosticLocation::createConditionalColonLoc(
672
                                            const ConditionalOperator *CO,
673
16
                                            const SourceManager &SM) {
674
16
  return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
675
16
}
676
677
PathDiagnosticLocation
678
PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME,
679
10
                                        const SourceManager &SM) {
680
10
681
10
  assert(ME->getMemberLoc().isValid() || ME->getBeginLoc().isValid());
682
10
683
10
  // In some cases, getMemberLoc isn't valid -- in this case we'll return with
684
10
  // some other related valid SourceLocation.
685
10
  if (ME->getMemberLoc().isValid())
686
6
    return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
687
4
688
4
  return PathDiagnosticLocation(ME->getBeginLoc(), SM, SingleLocK);
689
4
}
690
691
PathDiagnosticLocation
692
PathDiagnosticLocation::createBeginBrace(const CompoundStmt *CS,
693
0
                                         const SourceManager &SM) {
694
0
  SourceLocation L = CS->getLBracLoc();
695
0
  return PathDiagnosticLocation(L, SM, SingleLocK);
696
0
}
697
698
PathDiagnosticLocation
699
PathDiagnosticLocation::createEndBrace(const CompoundStmt *CS,
700
743
                                       const SourceManager &SM) {
701
743
  SourceLocation L = CS->getRBracLoc();
702
743
  return PathDiagnosticLocation(L, SM, SingleLocK);
703
743
}
704
705
PathDiagnosticLocation
706
PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
707
0
                                        const SourceManager &SM) {
708
0
  // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
709
0
  if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
710
0
    if (!CS->body_empty()) {
711
0
      SourceLocation Loc = (*CS->body_begin())->getBeginLoc();
712
0
      return PathDiagnosticLocation(Loc, SM, SingleLocK);
713
0
    }
714
0
715
0
  return PathDiagnosticLocation();
716
0
}
717
718
PathDiagnosticLocation
719
PathDiagnosticLocation::createDeclEnd(const LocationContext *LC,
720
153
                                      const SourceManager &SM) {
721
153
  SourceLocation L = LC->getDecl()->getBodyRBrace();
722
153
  return PathDiagnosticLocation(L, SM, SingleLocK);
723
153
}
724
725
PathDiagnosticLocation
726
PathDiagnosticLocation::create(const ProgramPoint& P,
727
1.66k
                               const SourceManager &SMng) {
728
1.66k
  const Stmt* S = nullptr;
729
1.66k
  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
730
296
    const CFGBlock *BSrc = BE->getSrc();
731
296
    if (BSrc->getTerminator().isVirtualBaseBranch()) {
732
110
      // TODO: VirtualBaseBranches should also appear for destructors.
733
110
      // In this case we should put the diagnostic at the end of decl.
734
110
      return PathDiagnosticLocation::createBegin(
735
110
          P.getLocationContext()->getDecl(), SMng);
736
110
737
186
    } else {
738
186
      S = BSrc->getTerminatorCondition();
739
186
      if (!S) {
740
10
        // If the BlockEdge has no terminator condition statement but its
741
10
        // source is the entry of the CFG (e.g. a checker crated the branch at
742
10
        // the beginning of a function), use the function's declaration instead.
743
10
        assert(BSrc == &BSrc->getParent()->getEntry() && "CFGBlock has no "
744
10
               "TerminatorCondition and is not the enrty block of the CFG");
745
10
        return PathDiagnosticLocation::createBegin(
746
10
            P.getLocationContext()->getDecl(), SMng);
747
10
      }
748
1.36k
    }
749
1.36k
  } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
750
1.27k
    S = SP->getStmt();
751
1.27k
    if (P.getAs<PostStmtPurgeDeadSymbols>())
752
0
      return PathDiagnosticLocation::createEnd(S, SMng, P.getLocationContext());
753
92
  } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
754
6
    return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
755
6
                                  SMng);
756
86
  } else if (Optional<PreImplicitCall> PIC = P.getAs<PreImplicitCall>()) {
757
0
    return PathDiagnosticLocation(PIC->getLocation(), SMng);
758
86
  } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
759
0
    return PathDiagnosticLocation(PIE->getLocation(), SMng);
760
86
  } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
761
3
    return getLocationForCaller(CE->getCalleeContext(),
762
3
                                CE->getLocationContext(),
763
3
                                SMng);
764
83
  } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
765
0
    return getLocationForCaller(CEE->getCalleeContext(),
766
0
                                CEE->getLocationContext(),
767
0
                                SMng);
768
83
  } else if (auto CEB = P.getAs<CallExitBegin>()) {
769
78
    if (const ReturnStmt *RS = CEB->getReturnStmt())
770
30
      return PathDiagnosticLocation::createBegin(RS, SMng,
771
30
                                                 CEB->getLocationContext());
772
48
    return PathDiagnosticLocation(
773
48
        CEB->getLocationContext()->getDecl()->getSourceRange().getEnd(), SMng);
774
48
  } else 
if (Optional<BlockEntrance> 5
BE5
= P.getAs<BlockEntrance>()) {
775
4
    CFGElement BlockFront = BE->getBlock()->front();
776
4
    if (auto StmtElt = BlockFront.getAs<CFGStmt>()) {
777
3
      return PathDiagnosticLocation(StmtElt->getStmt()->getBeginLoc(), SMng);
778
3
    } else 
if (auto 1
NewAllocElt1
= BlockFront.getAs<CFGNewAllocator>()) {
779
1
      return PathDiagnosticLocation(
780
1
          NewAllocElt->getAllocatorExpr()->getBeginLoc(), SMng);
781
1
    }
782
0
    llvm_unreachable("Unexpected CFG element at front of block");
783
1
  } else if (Optional<FunctionExitPoint> FE = P.getAs<FunctionExitPoint>()) {
784
1
    return PathDiagnosticLocation(FE->getStmt(), SMng,
785
1
                                  FE->getLocationContext());
786
1
  } else {
787
0
    llvm_unreachable("Unexpected ProgramPoint");
788
0
  }
789
1.45k
790
1.45k
  return PathDiagnosticLocation(S, SMng, P.getLocationContext());
791
1.45k
}
792
793
static const LocationContext *
794
7.91k
findTopAutosynthesizedParentContext(const LocationContext *LC) {
795
7.91k
  assert(LC->getAnalysisDeclContext()->isBodyAutosynthesized());
796
7.91k
  const LocationContext *ParentLC = LC->getParent();
797
7.91k
  assert(ParentLC && "We don't start analysis from autosynthesized code");
798
7.91k
  while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
799
0
    LC = ParentLC;
800
0
    ParentLC = LC->getParent();
801
0
    assert(ParentLC && "We don't start analysis from autosynthesized code");
802
0
  }
803
7.91k
  return LC;
804
7.91k
}
805
806
1.14M
const Stmt *PathDiagnosticLocation::getStmt(const ExplodedNode *N) {
807
1.14M
  // We cannot place diagnostics on autosynthesized code.
808
1.14M
  // Put them onto the call site through which we jumped into autosynthesized
809
1.14M
  // code for the first time.
810
1.14M
  const LocationContext *LC = N->getLocationContext();
811
1.14M
  if (LC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
812
7.91k
    // It must be a stack frame because we only autosynthesize functions.
813
7.91k
    return cast<StackFrameContext>(findTopAutosynthesizedParentContext(LC))
814
7.91k
        ->getCallSite();
815
7.91k
  }
816
1.13M
  // Otherwise, see if the node's program point directly points to a statement.
817
1.13M
  ProgramPoint P = N->getLocation();
818
1.13M
  if (auto SP = P.getAs<StmtPoint>())
819
988k
    return SP->getStmt();
820
150k
  if (auto BE = P.getAs<BlockEdge>())
821
53.9k
    return BE->getSrc()->getTerminatorStmt();
822
96.1k
  if (auto CE = P.getAs<CallEnter>())
823
539
    return CE->getCallExpr();
824
95.6k
  if (auto CEE = P.getAs<CallExitEnd>())
825
20.2k
    return CEE->getCalleeContext()->getCallSite();
826
75.4k
  if (auto PIPP = P.getAs<PostInitializer>())
827
8.15k
    return PIPP->getInitializer()->getInit();
828
67.2k
  if (auto CEB = P.getAs<CallExitBegin>())
829
20.3k
    return CEB->getReturnStmt();
830
46.9k
  if (auto FEP = P.getAs<FunctionExitPoint>())
831
1.50k
    return FEP->getStmt();
832
45.4k
833
45.4k
  return nullptr;
834
45.4k
}
835
836
986
const Stmt *PathDiagnosticLocation::getNextStmt(const ExplodedNode *N) {
837
1.78k
  for (N = N->getFirstSucc(); N; 
N = N->getFirstSucc()796
) {
838
1.62k
    if (const Stmt *S = getStmt(N)) {
839
835
      // Check if the statement is '?' or '&&'/'||'.  These are "merges",
840
835
      // not actual statement points.
841
835
      switch (S->getStmtClass()) {
842
835
        case Stmt::ChooseExprClass:
843
2
        case Stmt::BinaryConditionalOperatorClass:
844
2
        case Stmt::ConditionalOperatorClass:
845
2
          continue;
846
64
        case Stmt::BinaryOperatorClass: {
847
64
          BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
848
64
          if (Op == BO_LAnd || Op == BO_LOr)
849
0
            continue;
850
64
          break;
851
64
        }
852
769
        default:
853
769
          break;
854
833
      }
855
833
      // We found the statement, so return it.
856
833
      return S;
857
833
    }
858
1.62k
  }
859
986
860
986
  
return nullptr153
;
861
986
}
862
863
PathDiagnosticLocation
864
  PathDiagnosticLocation::createEndOfPath(const ExplodedNode *N,
865
30.2k
                                          const SourceManager &SM) {
866
30.2k
  assert(N && "Cannot create a location with a null node.");
867
30.2k
  const Stmt *S = getStmt(N);
868
30.2k
  const LocationContext *LC = N->getLocationContext();
869
30.2k
870
30.2k
  if (!S) {
871
433
    // If this is an implicit call, return the implicit call point location.
872
433
    if (Optional<PreImplicitCall> PIE = N->getLocationAs<PreImplicitCall>())
873
48
      return PathDiagnosticLocation(PIE->getLocation(), SM);
874
385
    if (auto FE = N->getLocationAs<FunctionExitPoint>()) {
875
385
      if (const ReturnStmt *RS = FE->getStmt())
876
0
        return PathDiagnosticLocation::createBegin(RS, SM, LC);
877
385
    }
878
385
    S = getNextStmt(N);
879
385
  }
880
30.2k
881
30.2k
  
if (30.2k
S30.2k
) {
882
30.0k
    ProgramPoint P = N->getLocation();
883
30.0k
884
30.0k
    // For member expressions, return the location of the '.' or '->'.
885
30.0k
    if (const auto *ME = dyn_cast<MemberExpr>(S))
886
10
      return PathDiagnosticLocation::createMemberLoc(ME, SM);
887
30.0k
888
30.0k
    // For binary operators, return the location of the operator.
889
30.0k
    if (const auto *B = dyn_cast<BinaryOperator>(S))
890
2.93k
      return PathDiagnosticLocation::createOperatorLoc(B, SM);
891
27.1k
892
27.1k
    if (P.getAs<PostStmtPurgeDeadSymbols>())
893
659
      return PathDiagnosticLocation::createEnd(S, SM, LC);
894
26.4k
895
26.4k
    if (S->getBeginLoc().isValid())
896
26.4k
      return PathDiagnosticLocation(S, SM, LC);
897
2
    return PathDiagnosticLocation(getValidSourceLocation(S, LC), SM);
898
2
  }
899
153
900
153
  return createDeclEnd(N->getLocationContext(), SM);
901
153
}
902
903
PathDiagnosticLocation PathDiagnosticLocation::createSingleLocation(
904
31
                                           const PathDiagnosticLocation &PDL) {
905
31
  FullSourceLoc L = PDL.asLocation();
906
31
  return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
907
31
}
908
909
FullSourceLoc
910
  PathDiagnosticLocation::genLocation(SourceLocation L,
911
90.9k
                                      LocationOrAnalysisDeclContext LAC) const {
912
90.9k
  assert(isValid());
913
90.9k
  // Note that we want a 'switch' here so that the compiler can warn us in
914
90.9k
  // case we add more cases.
915
90.9k
  switch (K) {
916
90.9k
    case SingleLocK:
917
15.5k
    case RangeK:
918
15.5k
      break;
919
75.1k
    case StmtK:
920
75.1k
      // Defensive checking.
921
75.1k
      if (!S)
922
0
        break;
923
75.1k
      return FullSourceLoc(getValidSourceLocation(S, LAC),
924
75.1k
                           const_cast<SourceManager&>(*SM));
925
75.1k
    case DeclK:
926
294
      // Defensive checking.
927
294
      if (!D)
928
0
        break;
929
294
      return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
930
15.5k
  }
931
15.5k
932
15.5k
  return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
933
15.5k
}
934
935
PathDiagnosticRange
936
91.1k
  PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
937
91.1k
  assert(isValid());
938
91.1k
  // Note that we want a 'switch' here so that the compiler can warn us in
939
91.1k
  // case we add more cases.
940
91.1k
  switch (K) {
941
91.1k
    case SingleLocK:
942
15.6k
      return PathDiagnosticRange(SourceRange(Loc,Loc), true);
943
91.1k
    case RangeK:
944
0
      break;
945
91.1k
    case StmtK: {
946
75.1k
      const Stmt *S = asStmt();
947
75.1k
      switch (S->getStmtClass()) {
948
75.1k
        default:
949
68.1k
          break;
950
75.1k
        case Stmt::DeclStmtClass: {
951
5.07k
          const auto *DS = cast<DeclStmt>(S);
952
5.07k
          if (DS->isSingleDecl()) {
953
5.05k
            // Should always be the case, but we'll be defensive.
954
5.05k
            return SourceRange(DS->getBeginLoc(),
955
5.05k
                               DS->getSingleDecl()->getLocation());
956
5.05k
          }
957
12
          break;
958
12
        }
959
12
          // FIXME: Provide better range information for different
960
12
          //  terminators.
961
1.93k
        case Stmt::IfStmtClass:
962
1.93k
        case Stmt::WhileStmtClass:
963
1.93k
        case Stmt::DoStmtClass:
964
1.93k
        case Stmt::ForStmtClass:
965
1.93k
        case Stmt::ChooseExprClass:
966
1.93k
        case Stmt::IndirectGotoStmtClass:
967
1.93k
        case Stmt::SwitchStmtClass:
968
1.93k
        case Stmt::BinaryConditionalOperatorClass:
969
1.93k
        case Stmt::ConditionalOperatorClass:
970
1.93k
        case Stmt::ObjCForCollectionStmtClass: {
971
1.93k
          SourceLocation L = getValidSourceLocation(S, LAC);
972
1.93k
          return SourceRange(L, L);
973
68.1k
        }
974
68.1k
      }
975
68.1k
      SourceRange R = S->getSourceRange();
976
68.1k
      if (R.isValid())
977
68.1k
        return R;
978
0
      break;
979
0
    }
980
294
    case DeclK:
981
294
      if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
982
1
        return MD->getSourceRange();
983
293
      if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
984
6
        if (Stmt *Body = FD->getBody())
985
6
          return Body->getSourceRange();
986
287
      }
987
287
      else {
988
287
        SourceLocation L = D->getLocation();
989
287
        return PathDiagnosticRange(SourceRange(L, L), true);
990
287
      }
991
0
  }
992
0
993
0
  return SourceRange(Loc, Loc);
994
0
}
995
996
32.2k
void PathDiagnosticLocation::flatten() {
997
32.2k
  if (K == StmtK) {
998
24.9k
    K = RangeK;
999
24.9k
    S = nullptr;
1000
24.9k
    D = nullptr;
1001
24.9k
  }
1002
7.26k
  else if (K == DeclK) {
1003
428
    K = SingleLocK;
1004
428
    S = nullptr;
1005
428
    D = nullptr;
1006
428
  }
1007
32.2k
}
1008
1009
//===----------------------------------------------------------------------===//
1010
// Manipulation of PathDiagnosticCallPieces.
1011
//===----------------------------------------------------------------------===//
1012
1013
std::shared_ptr<PathDiagnosticCallPiece>
1014
PathDiagnosticCallPiece::construct(const CallExitEnd &CE,
1015
6.70k
                                   const SourceManager &SM) {
1016
6.70k
  const Decl *caller = CE.getLocationContext()->getDecl();
1017
6.70k
  PathDiagnosticLocation pos = getLocationForCaller(CE.getCalleeContext(),
1018
6.70k
                                                    CE.getLocationContext(),
1019
6.70k
                                                    SM);
1020
6.70k
  return std::shared_ptr<PathDiagnosticCallPiece>(
1021
6.70k
      new PathDiagnosticCallPiece(caller, pos));
1022
6.70k
}
1023
1024
PathDiagnosticCallPiece *
1025
PathDiagnosticCallPiece::construct(PathPieces &path,
1026
193
                                   const Decl *caller) {
1027
193
  std::shared_ptr<PathDiagnosticCallPiece> C(
1028
193
      new PathDiagnosticCallPiece(path, caller));
1029
193
  path.clear();
1030
193
  auto *R = C.get();
1031
193
  path.push_front(std::move(C));
1032
193
  return R;
1033
193
}
1034
1035
void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
1036
6.89k
                                        const SourceManager &SM) {
1037
6.89k
  const StackFrameContext *CalleeCtx = CE.getCalleeContext();
1038
6.89k
  Callee = CalleeCtx->getDecl();
1039
6.89k
1040
6.89k
  callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
1041
6.89k
  callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
1042
6.89k
1043
6.89k
  // Autosynthesized property accessors are special because we'd never
1044
6.89k
  // pop back up to non-autosynthesized code until we leave them.
1045
6.89k
  // This is not generally true for autosynthesized callees, which may call
1046
6.89k
  // non-autosynthesized callbacks.
1047
6.89k
  // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
1048
6.89k
  // defaults to false.
1049
6.89k
  if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
1050
27
    IsCalleeAnAutosynthesizedPropertyAccessor = (
1051
27
        MD->isPropertyAccessor() &&
1052
27
        
CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized()2
);
1053
6.89k
}
1054
1055
static void describeTemplateParameters(raw_ostream &Out,
1056
                                       const ArrayRef<TemplateArgument> TAList,
1057
                                       const LangOptions &LO,
1058
                                       StringRef Prefix = StringRef(),
1059
                                       StringRef Postfix = StringRef());
1060
1061
static void describeTemplateParameter(raw_ostream &Out,
1062
                                      const TemplateArgument &TArg,
1063
133
                                      const LangOptions &LO) {
1064
133
1065
133
  if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
1066
36
    describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
1067
97
  } else {
1068
97
    TArg.print(PrintingPolicy(LO), Out);
1069
97
  }
1070
133
}
1071
1072
static void describeTemplateParameters(raw_ostream &Out,
1073
                                       const ArrayRef<TemplateArgument> TAList,
1074
                                       const LangOptions &LO,
1075
95
                                       StringRef Prefix, StringRef Postfix) {
1076
95
  if (TAList.empty())
1077
28
    return;
1078
67
1079
67
  Out << Prefix;
1080
133
  for (int I = 0, Last = TAList.size() - 1; I != Last; 
++I66
) {
1081
66
    describeTemplateParameter(Out, TAList[I], LO);
1082
66
    Out << ", ";
1083
66
  }
1084
67
  describeTemplateParameter(Out, TAList[TAList.size() - 1], LO);
1085
67
  Out << Postfix;
1086
67
}
1087
1088
static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
1089
218
                          StringRef Prefix = StringRef()) {
1090
218
  if (!D->getIdentifier())
1091
0
    return;
1092
218
  Out << Prefix << '\'' << *D;
1093
218
  if (const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
1094
17
    describeTemplateParameters(Out, T->getTemplateArgs().asArray(),
1095
17
                               D->getASTContext().getLangOpts(), "<", ">");
1096
218
1097
218
  Out << '\'';
1098
218
}
1099
1100
static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
1101
                             bool ExtendedDescription,
1102
1.62k
                             StringRef Prefix = StringRef()) {
1103
1.62k
  if (!D)
1104
0
    return false;
1105
1.62k
1106
1.62k
  if (isa<BlockDecl>(D)) {
1107
113
    if (ExtendedDescription)
1108
75
      Out << Prefix << "anonymous block";
1109
113
    return ExtendedDescription;
1110
113
  }
1111
1.51k
1112
1.51k
  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
1113
391
    Out << Prefix;
1114
391
    if (ExtendedDescription && 
!MD->isUserProvided()291
) {
1115
36
      if (MD->isExplicitlyDefaulted())
1116
10
        Out << "defaulted ";
1117
26
      else
1118
26
        Out << "implicit ";
1119
36
    }
1120
391
1121
391
    if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
1122
183
      if (CD->isDefaultConstructor())
1123
50
        Out << "default ";
1124
133
      else if (CD->isCopyConstructor())
1125
20
        Out << "copy ";
1126
113
      else if (CD->isMoveConstructor())
1127
28
        Out << "move ";
1128
183
1129
183
      Out << "constructor";
1130
183
      describeClass(Out, MD->getParent(), " for ");
1131
208
    } else if (isa<CXXDestructorDecl>(MD)) {
1132
67
      if (!MD->isUserProvided()) {
1133
7
        Out << "destructor";
1134
7
        describeClass(Out, MD->getParent(), " for ");
1135
60
      } else {
1136
60
        // Use ~Foo for explicitly-written destructors.
1137
60
        Out << "'" << *MD << "'";
1138
60
      }
1139
141
    } else if (MD->isCopyAssignmentOperator()) {
1140
14
        Out << "copy assignment operator";
1141
14
        describeClass(Out, MD->getParent(), " for ");
1142
127
    } else if (MD->isMoveAssignmentOperator()) {
1143
14
        Out << "move assignment operator";
1144
14
        describeClass(Out, MD->getParent(), " for ");
1145
113
    } else {
1146
113
      if (MD->getParent()->getIdentifier())
1147
78
        Out << "'" << *MD->getParent() << "::" << *MD << "'";
1148
35
      else
1149
35
        Out << "'" << *MD << "'";
1150
113
    }
1151
391
1152
391
    return true;
1153
391
  }
1154
1.12k
1155
1.12k
  Out << Prefix << '\'' << cast<NamedDecl>(*D);
1156
1.12k
1157
1.12k
  // Adding template parameters.
1158
1.12k
  if (const auto FD = dyn_cast<FunctionDecl>(D))
1159
1.00k
    if (const TemplateArgumentList *TAList =
1160
42
                                    FD->getTemplateSpecializationArgs())
1161
42
      describeTemplateParameters(Out, TAList->asArray(),
1162
42
                                 FD->getASTContext().getLangOpts(), "<", ">");
1163
1.12k
1164
1.12k
  Out << '\'';
1165
1.12k
  return true;
1166
1.12k
}
1167
1168
std::shared_ptr<PathDiagnosticEventPiece>
1169
962
PathDiagnosticCallPiece::getCallEnterEvent() const {
1170
962
  // We do not produce call enters and call exits for autosynthesized property
1171
962
  // accessors. We do generally produce them for other functions coming from
1172
962
  // the body farm because they may call callbacks that bring us back into
1173
962
  // visible code.
1174
962
  if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
1175
5
    return nullptr;
1176
957
1177
957
  SmallString<256> buf;
1178
957
  llvm::raw_svector_ostream Out(buf);
1179
957
1180
957
  Out << "Calling ";
1181
957
  describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
1182
957
1183
957
  assert(callEnter.asLocation().isValid());
1184
957
  return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
1185
957
}
1186
1187
std::shared_ptr<PathDiagnosticEventPiece>
1188
284
PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
1189
284
  if (!callEnterWithin.asLocation().isValid())
1190
0
    return nullptr;
1191
284
  if (Callee->isImplicit() || 
!Callee->hasBody()274
)
1192
20
    return nullptr;
1193
264
  if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
1194
48
    if (MD->isDefaulted())
1195
4
      return nullptr;
1196
260
1197
260
  SmallString<256> buf;
1198
260
  llvm::raw_svector_ostream Out(buf);
1199
260
1200
260
  Out << "Entered call";
1201
260
  describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
1202
260
1203
260
  return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
1204
260
}
1205
1206
std::shared_ptr<PathDiagnosticEventPiece>
1207
820
PathDiagnosticCallPiece::getCallExitEvent() const {
1208
820
  // We do not produce call enters and call exits for autosynthesized property
1209
820
  // accessors. We do generally produce them for other functions coming from
1210
820
  // the body farm because they may call callbacks that bring us back into
1211
820
  // visible code.
1212
820
  if (NoExit || 
IsCalleeAnAutosynthesizedPropertyAccessor448
)
1213
376
    return nullptr;
1214
444
1215
444
  SmallString<256> buf;
1216
444
  llvm::raw_svector_ostream Out(buf);
1217
444
1218
444
  if (!CallStackMessage.empty()) {
1219
34
    Out << CallStackMessage;
1220
410
  } else {
1221
410
    bool DidDescribe = describeCodeDecl(Out, Callee,
1222
410
                                        /*ExtendedDescription=*/false,
1223
410
                                        "Returning from ");
1224
410
    if (!DidDescribe)
1225
34
      Out << "Returning to caller";
1226
410
  }
1227
444
1228
444
  assert(callReturn.asLocation().isValid());
1229
444
  return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
1230
444
}
1231
1232
154
static void compute_path_size(const PathPieces &pieces, unsigned &size) {
1233
206
  for (const auto &I : pieces) {
1234
206
    const PathDiagnosticPiece *piece = I.get();
1235
206
    if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
1236
26
      compute_path_size(cp->path, size);
1237
180
    else
1238
180
      ++size;
1239
206
  }
1240
154
}
1241
1242
128
unsigned PathDiagnostic::full_size() {
1243
128
  unsigned size = 0;
1244
128
  compute_path_size(path, size);
1245
128
  return size;
1246
128
}
1247
1248
//===----------------------------------------------------------------------===//
1249
// FoldingSet profiling methods.
1250
//===----------------------------------------------------------------------===//
1251
1252
41.6k
void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
1253
41.6k
  ID.AddInteger(Range.getBegin().getRawEncoding());
1254
41.6k
  ID.AddInteger(Range.getEnd().getRawEncoding());
1255
41.6k
  ID.AddInteger(Loc.getRawEncoding());
1256
41.6k
}
1257
1258
2.43k
void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1259
2.43k
  ID.AddInteger((unsigned) getKind());
1260
2.43k
  ID.AddString(str);
1261
2.43k
  // FIXME: Add profiling support for code hints.
1262
2.43k
  ID.AddInteger((unsigned) getDisplayHint());
1263
2.43k
  ArrayRef<SourceRange> Ranges = getRanges();
1264
2.47k
  for (const auto &I : Ranges) {
1265
2.47k
    ID.AddInteger(I.getBegin().getRawEncoding());
1266
2.47k
    ID.AddInteger(I.getEnd().getRawEncoding());
1267
2.47k
  }
1268
2.43k
}
1269
1270
0
void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1271
0
  PathDiagnosticPiece::Profile(ID);
1272
0
  for (const auto &I : path)
1273
0
    ID.Add(*I);
1274
0
}
1275
1276
2.43k
void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1277
2.43k
  PathDiagnosticPiece::Profile(ID);
1278
2.43k
  ID.Add(Pos);
1279
2.43k
}
1280
1281
0
void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1282
0
  PathDiagnosticPiece::Profile(ID);
1283
0
  for (const auto &I : *this)
1284
0
    ID.Add(I);
1285
0
}
1286
1287
0
void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1288
0
  PathDiagnosticSpotPiece::Profile(ID);
1289
0
  for (const auto &I : subPieces)
1290
0
    ID.Add(*I);
1291
0
}
1292
1293
0
void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
1294
0
  PathDiagnosticSpotPiece::Profile(ID);
1295
0
}
1296
1297
139
void PathDiagnosticPopUpPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1298
139
  PathDiagnosticSpotPiece::Profile(ID);
1299
139
}
1300
1301
36.7k
void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
1302
36.7k
  ID.Add(getLocation());
1303
36.7k
  ID.AddString(BugType);
1304
36.7k
  ID.AddString(VerboseDesc);
1305
36.7k
  ID.AddString(Category);
1306
36.7k
}
1307
1308
0
void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1309
0
  Profile(ID);
1310
0
  for (const auto &I : path)
1311
0
    ID.Add(*I);
1312
0
  for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1313
0
    ID.AddString(*I);
1314
0
}
1315
1316
681
StackHintGenerator::~StackHintGenerator() = default;
1317
1318
20
std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){
1319
20
  if (!N)
1320
0
    return getMessageForSymbolNotFound();
1321
20
1322
20
  ProgramPoint P = N->getLocation();
1323
20
  CallExitEnd CExit = P.castAs<CallExitEnd>();
1324
20
1325
20
  // FIXME: Use CallEvent to abstract this over all calls.
1326
20
  const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
1327
20
  const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
1328
20
  if (!CE)
1329
1
    return {};
1330
19
1331
19
  // Check if one of the parameters are set to the interesting symbol.
1332
19
  unsigned ArgIndex = 0;
1333
19
  for (CallExpr::const_arg_iterator I = CE->arg_begin(),
1334
24
                                    E = CE->arg_end(); I != E; 
++I, ++ArgIndex5
){
1335
11
    SVal SV = N->getSVal(*I);
1336
11
1337
11
    // Check if the variable corresponding to the symbol is passed by value.
1338
11
    SymbolRef AS = SV.getAsLocSymbol();
1339
11
    if (AS == Sym) {
1340
4
      return getMessageForArg(*I, ArgIndex);
1341
4
    }
1342
7
1343
7
    // Check if the parameter is a pointer to the symbol.
1344
7
    if (Optional<loc::MemRegionVal> Reg = SV.getAs<loc::MemRegionVal>()) {
1345
5
      // Do not attempt to dereference void*.
1346
5
      if ((*I)->getType()->isVoidPointerType())
1347
0
        continue;
1348
5
      SVal PSV = N->getState()->getSVal(Reg->getRegion());
1349
5
      SymbolRef AS = PSV.getAsLocSymbol();
1350
5
      if (AS == Sym) {
1351
2
        return getMessageForArg(*I, ArgIndex);
1352
2
      }
1353
5
    }
1354
7
  }
1355
19
1356
19
  // Check if we are returning the interesting symbol.
1357
19
  SVal SV = N->getSVal(CE);
1358
13
  SymbolRef RetSym = SV.getAsLocSymbol();
1359
13
  if (RetSym == Sym) {
1360
7
    return getMessageForReturn(CE);
1361
7
  }
1362
6
1363
6
  return getMessageForSymbolNotFound();
1364
6
}
1365
1366
std::string StackHintGeneratorForSymbol::getMessageForArg(const Expr *ArgE,
1367
5
                                                          unsigned ArgIndex) {
1368
5
  // Printed parameters start at 1, not 0.
1369
5
  ++ArgIndex;
1370
5
1371
5
  SmallString<200> buf;
1372
5
  llvm::raw_svector_ostream os(buf);
1373
5
1374
5
  os << Msg << " via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1375
5
     << " parameter";
1376
5
1377
5
  return os.str();
1378
5
}
1379
1380
0
LLVM_DUMP_METHOD void PathPieces::dump() const {
1381
0
  unsigned index = 0;
1382
0
  for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
1383
0
    llvm::errs() << "[" << index++ << "]  ";
1384
0
    (*I)->dump();
1385
0
    llvm::errs() << "\n";
1386
0
  }
1387
0
}
1388
1389
0
LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const {
1390
0
  llvm::errs() << "CALL\n--------------\n";
1391
0
1392
0
  if (const Stmt *SLoc = getLocation().getStmtOrNull())
1393
0
    SLoc->dump();
1394
0
  else if (const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee()))
1395
0
    llvm::errs() << *ND << "\n";
1396
0
  else
1397
0
    getLocation().dump();
1398
0
}
1399
1400
0
LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const {
1401
0
  llvm::errs() << "EVENT\n--------------\n";
1402
0
  llvm::errs() << getString() << "\n";
1403
0
  llvm::errs() << " ---- at ----\n";
1404
0
  getLocation().dump();
1405
0
}
1406
1407
0
LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const {
1408
0
  llvm::errs() << "CONTROL\n--------------\n";
1409
0
  getStartLocation().dump();
1410
0
  llvm::errs() << " ---- to ----\n";
1411
0
  getEndLocation().dump();
1412
0
}
1413
1414
0
LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
1415
0
  llvm::errs() << "MACRO\n--------------\n";
1416
0
  // FIXME: Print which macro is being invoked.
1417
0
}
1418
1419
0
LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const {
1420
0
  llvm::errs() << "NOTE\n--------------\n";
1421
0
  llvm::errs() << getString() << "\n";
1422
0
  llvm::errs() << " ---- at ----\n";
1423
0
  getLocation().dump();
1424
0
}
1425
1426
0
LLVM_DUMP_METHOD void PathDiagnosticPopUpPiece::dump() const {
1427
0
  llvm::errs() << "POP-UP\n--------------\n";
1428
0
  llvm::errs() << getString() << "\n";
1429
0
  llvm::errs() << " ---- at ----\n";
1430
0
  getLocation().dump();
1431
0
}
1432
1433
0
LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const {
1434
0
  if (!isValid()) {
1435
0
    llvm::errs() << "<INVALID>\n";
1436
0
    return;
1437
0
  }
1438
0
1439
0
  switch (K) {
1440
0
  case RangeK:
1441
0
    // FIXME: actually print the range.
1442
0
    llvm::errs() << "<range>\n";
1443
0
    break;
1444
0
  case SingleLocK:
1445
0
    asLocation().dump();
1446
0
    llvm::errs() << "\n";
1447
0
    break;
1448
0
  case StmtK:
1449
0
    if (S)
1450
0
      S->dump();
1451
0
    else
1452
0
      llvm::errs() << "<NULL STMT>\n";
1453
0
    break;
1454
0
  case DeclK:
1455
0
    if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
1456
0
      llvm::errs() << *ND << "\n";
1457
0
    else if (isa<BlockDecl>(D))
1458
0
      // FIXME: Make this nicer.
1459
0
      llvm::errs() << "<block>\n";
1460
0
    else if (D)
1461
0
      llvm::errs() << "<unknown decl>\n";
1462
0
    else
1463
0
      llvm::errs() << "<NULL DECL>\n";
1464
0
    break;
1465
0
  }
1466
0
}