Clang Project

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