clang  9.0.0svn
PathDiagnostic.cpp
Go to the documentation of this file.
1 //===- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the PathDiagnostic-related interfaces.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/DeclBase.h"
17 #include "clang/AST/DeclCXX.h"
18 #include "clang/AST/DeclObjC.h"
19 #include "clang/AST/DeclTemplate.h"
20 #include "clang/AST/Expr.h"
21 #include "clang/AST/ExprCXX.h"
23 #include "clang/AST/ParentMap.h"
24 #include "clang/AST/Stmt.h"
25 #include "clang/AST/Type.h"
27 #include "clang/Analysis/CFG.h"
30 #include "clang/Basic/LLVM.h"
36 #include "llvm/ADT/ArrayRef.h"
37 #include "llvm/ADT/FoldingSet.h"
38 #include "llvm/ADT/None.h"
39 #include "llvm/ADT/Optional.h"
40 #include "llvm/ADT/STLExtras.h"
41 #include "llvm/ADT/SmallString.h"
42 #include "llvm/ADT/SmallVector.h"
43 #include "llvm/ADT/StringExtras.h"
44 #include "llvm/ADT/StringRef.h"
45 #include "llvm/Support/Casting.h"
46 #include "llvm/Support/ErrorHandling.h"
47 #include "llvm/Support/raw_ostream.h"
48 #include <cassert>
49 #include <cstring>
50 #include <memory>
51 #include <utility>
52 #include <vector>
53 
54 using namespace clang;
55 using namespace ento;
56 
58  for (const auto &P : subPieces) {
59  if (isa<PathDiagnosticEventPiece>(*P))
60  return true;
61  if (const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(P.get()))
62  if (MP->containsEvent())
63  return true;
64  }
65  return false;
66 }
67 
68 static StringRef StripTrailingDots(StringRef s) {
69  for (StringRef::size_type i = s.size(); i != 0; --i)
70  if (s[i - 1] != '.')
71  return s.substr(0, i);
72  return {};
73 }
74 
76  Kind k, DisplayHint hint)
77  : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
78 
80  : kind(k), Hint(hint) {}
81 
83 
85 
87 
89 
91 
93 
94 void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
95  bool ShouldFlattenMacros) const {
96  for (auto &Piece : *this) {
97  switch (Piece->getKind()) {
99  auto &Call = cast<PathDiagnosticCallPiece>(*Piece);
100  if (auto CallEnter = Call.getCallEnterEvent())
101  Current.push_back(std::move(CallEnter));
102  Call.path.flattenTo(Primary, Primary, ShouldFlattenMacros);
103  if (auto callExit = Call.getCallExitEvent())
104  Current.push_back(std::move(callExit));
105  break;
106  }
108  auto &Macro = cast<PathDiagnosticMacroPiece>(*Piece);
109  if (ShouldFlattenMacros) {
110  Macro.subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
111  } else {
112  Current.push_back(Piece);
113  PathPieces NewPath;
114  Macro.subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
115  // FIXME: This probably shouldn't mutate the original path piece.
116  Macro.subPieces = NewPath;
117  }
118  break;
119  }
123  Current.push_back(Piece);
124  break;
125  }
126  }
127 }
128 
130 
132  StringRef CheckName, const Decl *declWithIssue, StringRef bugtype,
133  StringRef verboseDesc, StringRef shortDesc, StringRef category,
134  PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique,
135  std::unique_ptr<FilesToLineNumsMap> ExecutedLines)
136  : CheckName(CheckName), DeclWithIssue(declWithIssue),
137  BugType(StripTrailingDots(bugtype)),
138  VerboseDesc(StripTrailingDots(verboseDesc)),
139  ShortDesc(StripTrailingDots(shortDesc)),
140  Category(StripTrailingDots(category)), UniqueingLoc(LocationToUnique),
141  UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)),
142  path(pathImpl) {}
143 
144 static PathDiagnosticCallPiece *
145 getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP,
146  const SourceManager &SMgr) {
147  SourceLocation CallLoc = CP->callEnter.asLocation();
148 
149  // If the call is within a macro, don't do anything (for now).
150  if (CallLoc.isMacroID())
151  return nullptr;
152 
153  assert(AnalysisManager::isInCodeFile(CallLoc, SMgr) &&
154  "The call piece should not be in a header file.");
155 
156  // Check if CP represents a path through a function outside of the main file.
157  if (!AnalysisManager::isInCodeFile(CP->callEnterWithin.asLocation(), SMgr))
158  return CP;
159 
160  const PathPieces &Path = CP->path;
161  if (Path.empty())
162  return nullptr;
163 
164  // Check if the last piece in the callee path is a call to a function outside
165  // of the main file.
166  if (auto *CPInner = dyn_cast<PathDiagnosticCallPiece>(Path.back().get()))
167  return getFirstStackedCallToHeaderFile(CPInner, SMgr);
168 
169  // Otherwise, the last piece is in the main file.
170  return nullptr;
171 }
172 
174  if (path.empty())
175  return;
176 
177  PathDiagnosticPiece *LastP = path.back().get();
178  assert(LastP);
179  const SourceManager &SMgr = LastP->getLocation().getManager();
180 
181  // We only need to check if the report ends inside headers, if the last piece
182  // is a call piece.
183  if (auto *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
184  CP = getFirstStackedCallToHeaderFile(CP, SMgr);
185  if (CP) {
186  // Mark the piece.
187  CP->setAsLastInMainSourceFile();
188 
189  // Update the path diagnostic message.
190  const auto *ND = dyn_cast<NamedDecl>(CP->getCallee());
191  if (ND) {
192  SmallString<200> buf;
193  llvm::raw_svector_ostream os(buf);
194  os << " (within a call to '" << ND->getDeclName() << "')";
195  appendToDesc(os.str());
196  }
197 
198  // Reset the report containing declaration and location.
199  DeclWithIssue = CP->getCaller();
200  Loc = CP->getLocation();
201 
202  return;
203  }
204  }
205 }
206 
207 void PathDiagnosticConsumer::anchor() {}
208 
210  // Delete the contents of the FoldingSet if it isn't empty already.
211  for (auto &Diag : Diags)
212  delete &Diag;
213 }
214 
216  std::unique_ptr<PathDiagnostic> D) {
217  if (!D || D->path.empty())
218  return;
219 
220  // We need to flatten the locations (convert Stmt* to locations) because
221  // the referenced statements may be freed by the time the diagnostics
222  // are emitted.
223  D->flattenLocations();
224 
225  // If the PathDiagnosticConsumer does not support diagnostics that
226  // cross file boundaries, prune out such diagnostics now.
227  if (!supportsCrossFileDiagnostics()) {
228  // Verify that the entire path is from the same FileID.
229  FileID FID;
230  const SourceManager &SMgr = D->path.front()->getLocation().getManager();
232  WorkList.push_back(&D->path);
233  SmallString<128> buf;
234  llvm::raw_svector_ostream warning(buf);
235  warning << "warning: Path diagnostic report is not generated. Current "
236  << "output format does not support diagnostics that cross file "
237  << "boundaries. Refer to --analyzer-output for valid output "
238  << "formats\n";
239 
240  while (!WorkList.empty()) {
241  const PathPieces &path = *WorkList.pop_back_val();
242 
243  for (const auto &I : path) {
244  const PathDiagnosticPiece *piece = I.get();
246 
247  if (FID.isInvalid()) {
248  FID = SMgr.getFileID(L);
249  } else if (SMgr.getFileID(L) != FID) {
250  llvm::errs() << warning.str();
251  return;
252  }
253 
254  // Check the source ranges.
255  ArrayRef<SourceRange> Ranges = piece->getRanges();
256  for (const auto &I : Ranges) {
257  SourceLocation L = SMgr.getExpansionLoc(I.getBegin());
258  if (!L.isFileID() || SMgr.getFileID(L) != FID) {
259  llvm::errs() << warning.str();
260  return;
261  }
262  L = SMgr.getExpansionLoc(I.getEnd());
263  if (!L.isFileID() || SMgr.getFileID(L) != FID) {
264  llvm::errs() << warning.str();
265  return;
266  }
267  }
268 
269  if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece))
270  WorkList.push_back(&call->path);
271  else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece))
272  WorkList.push_back(&macro->subPieces);
273  }
274  }
275 
276  if (FID.isInvalid())
277  return; // FIXME: Emit a warning?
278  }
279 
280  // Profile the node to see if we already have something matching it
281  llvm::FoldingSetNodeID profile;
282  D->Profile(profile);
283  void *InsertPos = nullptr;
284 
285  if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
286  // Keep the PathDiagnostic with the shorter path.
287  // Note, the enclosing routine is called in deterministic order, so the
288  // results will be consistent between runs (no reason to break ties if the
289  // size is the same).
290  const unsigned orig_size = orig->full_size();
291  const unsigned new_size = D->full_size();
292  if (orig_size <= new_size)
293  return;
294 
295  assert(orig != D.get());
296  Diags.RemoveNode(orig);
297  delete orig;
298  }
299 
300  Diags.InsertNode(D.release());
301 }
302 
303 static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y);
304 
305 static Optional<bool>
306 compareControlFlow(const PathDiagnosticControlFlowPiece &X,
307  const PathDiagnosticControlFlowPiece &Y) {
308  FullSourceLoc XSL = X.getStartLocation().asLocation();
309  FullSourceLoc YSL = Y.getStartLocation().asLocation();
310  if (XSL != YSL)
311  return XSL.isBeforeInTranslationUnitThan(YSL);
312  FullSourceLoc XEL = X.getEndLocation().asLocation();
313  FullSourceLoc YEL = Y.getEndLocation().asLocation();
314  if (XEL != YEL)
315  return XEL.isBeforeInTranslationUnitThan(YEL);
316  return None;
317 }
318 
320  const PathDiagnosticMacroPiece &Y) {
321  return comparePath(X.subPieces, Y.subPieces);
322 }
323 
324 static Optional<bool> compareCall(const PathDiagnosticCallPiece &X,
325  const PathDiagnosticCallPiece &Y) {
326  FullSourceLoc X_CEL = X.callEnter.asLocation();
327  FullSourceLoc Y_CEL = Y.callEnter.asLocation();
328  if (X_CEL != Y_CEL)
329  return X_CEL.isBeforeInTranslationUnitThan(Y_CEL);
330  FullSourceLoc X_CEWL = X.callEnterWithin.asLocation();
331  FullSourceLoc Y_CEWL = Y.callEnterWithin.asLocation();
332  if (X_CEWL != Y_CEWL)
333  return X_CEWL.isBeforeInTranslationUnitThan(Y_CEWL);
334  FullSourceLoc X_CRL = X.callReturn.asLocation();
335  FullSourceLoc Y_CRL = Y.callReturn.asLocation();
336  if (X_CRL != Y_CRL)
337  return X_CRL.isBeforeInTranslationUnitThan(Y_CRL);
338  return comparePath(X.path, Y.path);
339 }
340 
342  const PathDiagnosticPiece &Y) {
343  if (X.getKind() != Y.getKind())
344  return X.getKind() < Y.getKind();
345 
346  FullSourceLoc XL = X.getLocation().asLocation();
347  FullSourceLoc YL = Y.getLocation().asLocation();
348  if (XL != YL)
349  return XL.isBeforeInTranslationUnitThan(YL);
350 
351  if (X.getString() != Y.getString())
352  return X.getString() < Y.getString();
353 
354  if (X.getRanges().size() != Y.getRanges().size())
355  return X.getRanges().size() < Y.getRanges().size();
356 
357  const SourceManager &SM = XL.getManager();
358 
359  for (unsigned i = 0, n = X.getRanges().size(); i < n; ++i) {
360  SourceRange XR = X.getRanges()[i];
361  SourceRange YR = Y.getRanges()[i];
362  if (XR != YR) {
363  if (XR.getBegin() != YR.getBegin())
364  return SM.isBeforeInTranslationUnit(XR.getBegin(), YR.getBegin());
365  return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd());
366  }
367  }
368 
369  switch (X.getKind()) {
371  return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X),
372  cast<PathDiagnosticControlFlowPiece>(Y));
375  return None;
377  return compareMacro(cast<PathDiagnosticMacroPiece>(X),
378  cast<PathDiagnosticMacroPiece>(Y));
380  return compareCall(cast<PathDiagnosticCallPiece>(X),
381  cast<PathDiagnosticCallPiece>(Y));
382  }
383  llvm_unreachable("all cases handled");
384 }
385 
386 static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) {
387  if (X.size() != Y.size())
388  return X.size() < Y.size();
389 
390  PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
391  PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
392 
393  for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) {
394  Optional<bool> b = comparePiece(**X_I, **Y_I);
395  if (b.hasValue())
396  return b.getValue();
397  }
398 
399  return None;
400 }
401 
403  std::pair<FileID, unsigned> XOffs = XL.getDecomposedLoc();
404  std::pair<FileID, unsigned> YOffs = YL.getDecomposedLoc();
405  const SourceManager &SM = XL.getManager();
406  std::pair<bool, bool> InSameTU = SM.isInTheSameTranslationUnit(XOffs, YOffs);
407  if (InSameTU.first)
408  return XL.isBeforeInTranslationUnitThan(YL);
409  const FileEntry *XFE = SM.getFileEntryForID(XL.getSpellingLoc().getFileID());
410  const FileEntry *YFE = SM.getFileEntryForID(YL.getSpellingLoc().getFileID());
411  if (!XFE || !YFE)
412  return XFE && !YFE;
413  int NameCmp = XFE->getName().compare(YFE->getName());
414  if (NameCmp != 0)
415  return NameCmp == -1;
416  // Last resort: Compare raw file IDs that are possibly expansions.
417  return XL.getFileID() < YL.getFileID();
418 }
419 
420 static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
421  FullSourceLoc XL = X.getLocation().asLocation();
422  FullSourceLoc YL = Y.getLocation().asLocation();
423  if (XL != YL)
424  return compareCrossTUSourceLocs(XL, YL);
425  if (X.getBugType() != Y.getBugType())
426  return X.getBugType() < Y.getBugType();
427  if (X.getCategory() != Y.getCategory())
428  return X.getCategory() < Y.getCategory();
429  if (X.getVerboseDescription() != Y.getVerboseDescription())
430  return X.getVerboseDescription() < Y.getVerboseDescription();
431  if (X.getShortDescription() != Y.getShortDescription())
432  return X.getShortDescription() < Y.getShortDescription();
433  if (X.getDeclWithIssue() != Y.getDeclWithIssue()) {
434  const Decl *XD = X.getDeclWithIssue();
435  if (!XD)
436  return true;
437  const Decl *YD = Y.getDeclWithIssue();
438  if (!YD)
439  return false;
440  SourceLocation XDL = XD->getLocation();
441  SourceLocation YDL = YD->getLocation();
442  if (XDL != YDL) {
443  const SourceManager &SM = XL.getManager();
444  return compareCrossTUSourceLocs(FullSourceLoc(XDL, SM),
445  FullSourceLoc(YDL, SM));
446  }
447  }
448  PathDiagnostic::meta_iterator XI = X.meta_begin(), XE = X.meta_end();
449  PathDiagnostic::meta_iterator YI = Y.meta_begin(), YE = Y.meta_end();
450  if (XE - XI != YE - YI)
451  return (XE - XI) < (YE - YI);
452  for ( ; XI != XE ; ++XI, ++YI) {
453  if (*XI != *YI)
454  return (*XI) < (*YI);
455  }
456  Optional<bool> b = comparePath(X.path, Y.path);
457  assert(b.hasValue());
458  return b.getValue();
459 }
460 
463  if (flushed)
464  return;
465 
466  flushed = true;
467 
468  std::vector<const PathDiagnostic *> BatchDiags;
469  for (const auto &D : Diags)
470  BatchDiags.push_back(&D);
471 
472  // Sort the diagnostics so that they are always emitted in a deterministic
473  // order.
474  int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
475  [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
476  assert(*X != *Y && "PathDiagnostics not uniqued!");
477  if (compare(**X, **Y))
478  return -1;
479  assert(compare(**Y, **X) && "Not a total order!");
480  return 1;
481  };
482  array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
483 
484  FlushDiagnosticsImpl(BatchDiags, Files);
485 
486  // Delete the flushed diagnostics.
487  for (const auto D : BatchDiags)
488  delete D;
489 
490  // Clear out the FoldingSet.
491  Diags.clear();
492 }
493 
495  for (PDFileEntry &Entry : Set)
496  Entry.~PDFileEntry();
497 }
498 
500  StringRef ConsumerName,
501  StringRef FileName) {
502  llvm::FoldingSetNodeID NodeID;
503  NodeID.Add(PD);
504  void *InsertPos;
505  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
506  if (!Entry) {
507  Entry = Alloc.Allocate<PDFileEntry>();
508  Entry = new (Entry) PDFileEntry(NodeID);
509  Set.InsertNode(Entry, InsertPos);
510  }
511 
512  // Allocate persistent storage for the file name.
513  char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
514  memcpy(FileName_cstr, FileName.data(), FileName.size());
515 
516  Entry->files.push_back(std::make_pair(ConsumerName,
517  StringRef(FileName_cstr,
518  FileName.size())));
519 }
520 
523  llvm::FoldingSetNodeID NodeID;
524  NodeID.Add(PD);
525  void *InsertPos;
526  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
527  if (!Entry)
528  return nullptr;
529  return &Entry->files;
530 }
531 
532 //===----------------------------------------------------------------------===//
533 // PathDiagnosticLocation methods.
534 //===----------------------------------------------------------------------===//
535 
538  bool UseEnd = false) {
539  SourceLocation L = UseEnd ? S->getEndLoc() : S->getBeginLoc();
540  assert(!LAC.isNull() && "A valid LocationContext or AnalysisDeclContext should "
541  "be passed to PathDiagnosticLocation upon creation.");
542 
543  // S might be a temporary statement that does not have a location in the
544  // source code, so find an enclosing statement and use its location.
545  if (!L.isValid()) {
546  AnalysisDeclContext *ADC;
547  if (LAC.is<const LocationContext*>())
548  ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext();
549  else
550  ADC = LAC.get<AnalysisDeclContext*>();
551 
552  ParentMap &PM = ADC->getParentMap();
553 
554  const Stmt *Parent = S;
555  do {
556  Parent = PM.getParent(Parent);
557 
558  // In rare cases, we have implicit top-level expressions,
559  // such as arguments for implicit member initializers.
560  // In this case, fall back to the start of the body (even if we were
561  // asked for the statement end location).
562  if (!Parent) {
563  const Stmt *Body = ADC->getBody();
564  if (Body)
565  L = Body->getBeginLoc();
566  else
567  L = ADC->getDecl()->getEndLoc();
568  break;
569  }
570 
571  L = UseEnd ? Parent->getEndLoc() : Parent->getBeginLoc();
572  } while (!L.isValid());
573  }
574 
575  return L;
576 }
577 
578 static PathDiagnosticLocation
580  const LocationContext *CallerCtx,
581  const SourceManager &SM) {
582  const CFGBlock &Block = *SFC->getCallSiteBlock();
583  CFGElement Source = Block[SFC->getIndex()];
584 
585  switch (Source.getKind()) {
589  return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
590  SM, CallerCtx);
592  const CFGInitializer &Init = Source.castAs<CFGInitializer>();
593  return PathDiagnosticLocation(Init.getInitializer()->getInit(),
594  SM, CallerCtx);
595  }
597  const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
599  SM, CallerCtx);
600  }
601  case CFGElement::DeleteDtor: {
602  const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
603  return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
604  }
606  case CFGElement::MemberDtor: {
607  const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
608  if (const Stmt *CallerBody = CallerInfo->getBody())
609  return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
610  return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
611  }
613  const CFGNewAllocator &Alloc = Source.castAs<CFGNewAllocator>();
614  return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerCtx);
615  }
617  // Temporary destructors are for temporaries. They die immediately at around
618  // the location of CXXBindTemporaryExpr. If they are lifetime-extended,
619  // they'd be dealt with via an AutomaticObjectDtor instead.
620  const auto &Dtor = Source.castAs<CFGTemporaryDtor>();
621  return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM,
622  CallerCtx);
623  }
626  llvm_unreachable("not yet implemented!");
629  llvm_unreachable("CFGElement kind should not be on callsite!");
630  }
631 
632  llvm_unreachable("Unknown CFGElement kind");
633 }
634 
635 PathDiagnosticLocation
637  const SourceManager &SM) {
638  return PathDiagnosticLocation(D->getBeginLoc(), SM, SingleLocK);
639 }
640 
643  const SourceManager &SM,
646  SM, SingleLocK);
647 }
648 
651  const SourceManager &SM,
653  if (const auto *CS = dyn_cast<CompoundStmt>(S))
654  return createEndBrace(CS, SM);
655  return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
656  SM, SingleLocK);
657 }
658 
661  const SourceManager &SM) {
662  return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
663 }
664 
667  const ConditionalOperator *CO,
668  const SourceManager &SM) {
669  return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
670 }
671 
674  const SourceManager &SM) {
675  return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
676 }
677 
680  const SourceManager &SM) {
681  SourceLocation L = CS->getLBracLoc();
682  return PathDiagnosticLocation(L, SM, SingleLocK);
683 }
684 
687  const SourceManager &SM) {
688  SourceLocation L = CS->getRBracLoc();
689  return PathDiagnosticLocation(L, SM, SingleLocK);
690 }
691 
694  const SourceManager &SM) {
695  // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
696  if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
697  if (!CS->body_empty()) {
698  SourceLocation Loc = (*CS->body_begin())->getBeginLoc();
699  return PathDiagnosticLocation(Loc, SM, SingleLocK);
700  }
701 
702  return PathDiagnosticLocation();
703 }
704 
707  const SourceManager &SM) {
708  SourceLocation L = LC->getDecl()->getBodyRBrace();
709  return PathDiagnosticLocation(L, SM, SingleLocK);
710 }
711 
714  const SourceManager &SMng) {
715  const Stmt* S = nullptr;
716  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
717  const CFGBlock *BSrc = BE->getSrc();
718  S = BSrc->getTerminatorCondition();
719  } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
720  S = SP->getStmt();
723  } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
724  return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
725  SMng);
726  } else if (Optional<PreImplicitCall> PIC = P.getAs<PreImplicitCall>()) {
727  return PathDiagnosticLocation(PIC->getLocation(), SMng);
728  } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
729  return PathDiagnosticLocation(PIE->getLocation(), SMng);
730  } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
731  return getLocationForCaller(CE->getCalleeContext(),
732  CE->getLocationContext(),
733  SMng);
734  } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
735  return getLocationForCaller(CEE->getCalleeContext(),
736  CEE->getLocationContext(),
737  SMng);
738  } else if (auto CEB = P.getAs<CallExitBegin>()) {
739  if (const ReturnStmt *RS = CEB->getReturnStmt())
740  return PathDiagnosticLocation::createBegin(RS, SMng,
741  CEB->getLocationContext());
742  return PathDiagnosticLocation(
743  CEB->getLocationContext()->getDecl()->getSourceRange().getEnd(), SMng);
744  } else if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
745  CFGElement BlockFront = BE->getBlock()->front();
746  if (auto StmtElt = BlockFront.getAs<CFGStmt>()) {
747  return PathDiagnosticLocation(StmtElt->getStmt()->getBeginLoc(), SMng);
748  } else if (auto NewAllocElt = BlockFront.getAs<CFGNewAllocator>()) {
749  return PathDiagnosticLocation(
750  NewAllocElt->getAllocatorExpr()->getBeginLoc(), SMng);
751  }
752  llvm_unreachable("Unexpected CFG element at front of block");
753  } else {
754  llvm_unreachable("Unexpected ProgramPoint");
755  }
756 
757  return PathDiagnosticLocation(S, SMng, P.getLocationContext());
758 }
759 
760 static const LocationContext *
763  const LocationContext *ParentLC = LC->getParent();
764  assert(ParentLC && "We don't start analysis from autosynthesized code");
765  while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
766  LC = ParentLC;
767  ParentLC = LC->getParent();
768  assert(ParentLC && "We don't start analysis from autosynthesized code");
769  }
770  return LC;
771 }
772 
774  // We cannot place diagnostics on autosynthesized code.
775  // Put them onto the call site through which we jumped into autosynthesized
776  // code for the first time.
777  const LocationContext *LC = N->getLocationContext();
779  // It must be a stack frame because we only autosynthesize functions.
780  return cast<StackFrameContext>(findTopAutosynthesizedParentContext(LC))
781  ->getCallSite();
782  }
783  // Otherwise, see if the node's program point directly points to a statement.
784  ProgramPoint P = N->getLocation();
785  if (auto SP = P.getAs<StmtPoint>())
786  return SP->getStmt();
787  if (auto BE = P.getAs<BlockEdge>())
788  return BE->getSrc()->getTerminator();
789  if (auto CE = P.getAs<CallEnter>())
790  return CE->getCallExpr();
791  if (auto CEE = P.getAs<CallExitEnd>())
792  return CEE->getCalleeContext()->getCallSite();
793  if (auto PIPP = P.getAs<PostInitializer>())
794  return PIPP->getInitializer()->getInit();
795  if (auto CEB = P.getAs<CallExitBegin>())
796  return CEB->getReturnStmt();
797  if (auto FEP = P.getAs<FunctionExitPoint>())
798  return FEP->getStmt();
799 
800  return nullptr;
801 }
802 
804  for (N = N->getFirstSucc(); N; N = N->getFirstSucc()) {
805  if (const Stmt *S = getStmt(N)) {
806  // Check if the statement is '?' or '&&'/'||'. These are "merges",
807  // not actual statement points.
808  switch (S->getStmtClass()) {
809  case Stmt::ChooseExprClass:
810  case Stmt::BinaryConditionalOperatorClass:
811  case Stmt::ConditionalOperatorClass:
812  continue;
813  case Stmt::BinaryOperatorClass: {
814  BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
815  if (Op == BO_LAnd || Op == BO_LOr)
816  continue;
817  break;
818  }
819  default:
820  break;
821  }
822  // We found the statement, so return it.
823  return S;
824  }
825  }
826 
827  return nullptr;
828 }
829 
832  const SourceManager &SM) {
833  assert(N && "Cannot create a location with a null node.");
834  const Stmt *S = getStmt(N);
835  const LocationContext *LC = N->getLocationContext();
836 
837  if (!S) {
838  // If this is an implicit call, return the implicit call point location.
840  return PathDiagnosticLocation(PIE->getLocation(), SM);
841  if (auto FE = N->getLocationAs<FunctionExitPoint>()) {
842  if (const ReturnStmt *RS = FE->getStmt())
843  return PathDiagnosticLocation::createBegin(RS, SM, LC);
844  }
845  S = getNextStmt(N);
846  }
847 
848  if (S) {
849  ProgramPoint P = N->getLocation();
850 
851  // For member expressions, return the location of the '.' or '->'.
852  if (const auto *ME = dyn_cast<MemberExpr>(S))
854 
855  // For binary operators, return the location of the operator.
856  if (const auto *B = dyn_cast<BinaryOperator>(S))
858 
860  return PathDiagnosticLocation::createEnd(S, SM, LC);
861 
862  if (S->getBeginLoc().isValid())
863  return PathDiagnosticLocation(S, SM, LC);
865  }
866 
867  return createDeclEnd(N->getLocationContext(), SM);
868 }
869 
871  const PathDiagnosticLocation &PDL) {
872  FullSourceLoc L = PDL.asLocation();
873  return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
874 }
875 
877  PathDiagnosticLocation::genLocation(SourceLocation L,
878  LocationOrAnalysisDeclContext LAC) const {
879  assert(isValid());
880  // Note that we want a 'switch' here so that the compiler can warn us in
881  // case we add more cases.
882  switch (K) {
883  case SingleLocK:
884  case RangeK:
885  break;
886  case StmtK:
887  // Defensive checking.
888  if (!S)
889  break;
890  return FullSourceLoc(getValidSourceLocation(S, LAC),
891  const_cast<SourceManager&>(*SM));
892  case DeclK:
893  // Defensive checking.
894  if (!D)
895  break;
896  return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
897  }
898 
899  return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
900 }
901 
903  PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
904  assert(isValid());
905  // Note that we want a 'switch' here so that the compiler can warn us in
906  // case we add more cases.
907  switch (K) {
908  case SingleLocK:
909  return PathDiagnosticRange(SourceRange(Loc,Loc), true);
910  case RangeK:
911  break;
912  case StmtK: {
913  const Stmt *S = asStmt();
914  switch (S->getStmtClass()) {
915  default:
916  break;
917  case Stmt::DeclStmtClass: {
918  const auto *DS = cast<DeclStmt>(S);
919  if (DS->isSingleDecl()) {
920  // Should always be the case, but we'll be defensive.
921  return SourceRange(DS->getBeginLoc(),
922  DS->getSingleDecl()->getLocation());
923  }
924  break;
925  }
926  // FIXME: Provide better range information for different
927  // terminators.
928  case Stmt::IfStmtClass:
929  case Stmt::WhileStmtClass:
930  case Stmt::DoStmtClass:
931  case Stmt::ForStmtClass:
932  case Stmt::ChooseExprClass:
933  case Stmt::IndirectGotoStmtClass:
934  case Stmt::SwitchStmtClass:
935  case Stmt::BinaryConditionalOperatorClass:
936  case Stmt::ConditionalOperatorClass:
937  case Stmt::ObjCForCollectionStmtClass: {
939  return SourceRange(L, L);
940  }
941  }
942  SourceRange R = S->getSourceRange();
943  if (R.isValid())
944  return R;
945  break;
946  }
947  case DeclK:
948  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
949  return MD->getSourceRange();
950  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
951  if (Stmt *Body = FD->getBody())
952  return Body->getSourceRange();
953  }
954  else {
955  SourceLocation L = D->getLocation();
956  return PathDiagnosticRange(SourceRange(L, L), true);
957  }
958  }
959 
960  return SourceRange(Loc, Loc);
961 }
962 
964  if (K == StmtK) {
965  K = RangeK;
966  S = nullptr;
967  D = nullptr;
968  }
969  else if (K == DeclK) {
970  K = SingleLocK;
971  S = nullptr;
972  D = nullptr;
973  }
974 }
975 
976 //===----------------------------------------------------------------------===//
977 // Manipulation of PathDiagnosticCallPieces.
978 //===----------------------------------------------------------------------===//
979 
980 std::shared_ptr<PathDiagnosticCallPiece>
982  const SourceManager &SM) {
983  const Decl *caller = CE.getLocationContext()->getDecl();
985  CE.getLocationContext(),
986  SM);
987  return std::shared_ptr<PathDiagnosticCallPiece>(
988  new PathDiagnosticCallPiece(caller, pos));
989 }
990 
993  const Decl *caller) {
994  std::shared_ptr<PathDiagnosticCallPiece> C(
995  new PathDiagnosticCallPiece(path, caller));
996  path.clear();
997  auto *R = C.get();
998  path.push_front(std::move(C));
999  return R;
1000 }
1001 
1003  const SourceManager &SM) {
1004  const StackFrameContext *CalleeCtx = CE.getCalleeContext();
1005  Callee = CalleeCtx->getDecl();
1006 
1007  callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
1008  callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
1009 
1010  // Autosynthesized property accessors are special because we'd never
1011  // pop back up to non-autosynthesized code until we leave them.
1012  // This is not generally true for autosynthesized callees, which may call
1013  // non-autosynthesized callbacks.
1014  // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
1015  // defaults to false.
1016  if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
1017  IsCalleeAnAutosynthesizedPropertyAccessor = (
1018  MD->isPropertyAccessor() &&
1020 }
1021 
1022 static void describeTemplateParameters(raw_ostream &Out,
1023  const ArrayRef<TemplateArgument> TAList,
1024  const LangOptions &LO,
1025  StringRef Prefix = StringRef(),
1026  StringRef Postfix = StringRef());
1027 
1028 static void describeTemplateParameter(raw_ostream &Out,
1029  const TemplateArgument &TArg,
1030  const LangOptions &LO) {
1031 
1032  if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
1033  describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
1034  } else {
1035  TArg.print(PrintingPolicy(LO), Out);
1036  }
1037 }
1038 
1039 static void describeTemplateParameters(raw_ostream &Out,
1040  const ArrayRef<TemplateArgument> TAList,
1041  const LangOptions &LO,
1042  StringRef Prefix, StringRef Postfix) {
1043  if (TAList.empty())
1044  return;
1045 
1046  Out << Prefix;
1047  for (int I = 0, Last = TAList.size() - 1; I != Last; ++I) {
1048  describeTemplateParameter(Out, TAList[I], LO);
1049  Out << ", ";
1050  }
1051  describeTemplateParameter(Out, TAList[TAList.size() - 1], LO);
1052  Out << Postfix;
1053 }
1054 
1055 static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
1056  StringRef Prefix = StringRef()) {
1057  if (!D->getIdentifier())
1058  return;
1059  Out << Prefix << '\'' << *D;
1060  if (const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
1061  describeTemplateParameters(Out, T->getTemplateArgs().asArray(),
1062  D->getASTContext().getLangOpts(), "<", ">");
1063 
1064  Out << '\'';
1065 }
1066 
1067 static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
1068  bool ExtendedDescription,
1069  StringRef Prefix = StringRef()) {
1070  if (!D)
1071  return false;
1072 
1073  if (isa<BlockDecl>(D)) {
1074  if (ExtendedDescription)
1075  Out << Prefix << "anonymous block";
1076  return ExtendedDescription;
1077  }
1078 
1079  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
1080  Out << Prefix;
1081  if (ExtendedDescription && !MD->isUserProvided()) {
1082  if (MD->isExplicitlyDefaulted())
1083  Out << "defaulted ";
1084  else
1085  Out << "implicit ";
1086  }
1087 
1088  if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
1089  if (CD->isDefaultConstructor())
1090  Out << "default ";
1091  else if (CD->isCopyConstructor())
1092  Out << "copy ";
1093  else if (CD->isMoveConstructor())
1094  Out << "move ";
1095 
1096  Out << "constructor";
1097  describeClass(Out, MD->getParent(), " for ");
1098  } else if (isa<CXXDestructorDecl>(MD)) {
1099  if (!MD->isUserProvided()) {
1100  Out << "destructor";
1101  describeClass(Out, MD->getParent(), " for ");
1102  } else {
1103  // Use ~Foo for explicitly-written destructors.
1104  Out << "'" << *MD << "'";
1105  }
1106  } else if (MD->isCopyAssignmentOperator()) {
1107  Out << "copy assignment operator";
1108  describeClass(Out, MD->getParent(), " for ");
1109  } else if (MD->isMoveAssignmentOperator()) {
1110  Out << "move assignment operator";
1111  describeClass(Out, MD->getParent(), " for ");
1112  } else {
1113  if (MD->getParent()->getIdentifier())
1114  Out << "'" << *MD->getParent() << "::" << *MD << "'";
1115  else
1116  Out << "'" << *MD << "'";
1117  }
1118 
1119  return true;
1120  }
1121 
1122  Out << Prefix << '\'' << cast<NamedDecl>(*D);
1123 
1124  // Adding template parameters.
1125  if (const auto FD = dyn_cast<FunctionDecl>(D))
1126  if (const TemplateArgumentList *TAList =
1127  FD->getTemplateSpecializationArgs())
1128  describeTemplateParameters(Out, TAList->asArray(),
1129  FD->getASTContext().getLangOpts(), "<", ">");
1130 
1131  Out << '\'';
1132  return true;
1133 }
1134 
1135 std::shared_ptr<PathDiagnosticEventPiece>
1137  // We do not produce call enters and call exits for autosynthesized property
1138  // accessors. We do generally produce them for other functions coming from
1139  // the body farm because they may call callbacks that bring us back into
1140  // visible code.
1141  if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
1142  return nullptr;
1143 
1144  SmallString<256> buf;
1145  llvm::raw_svector_ostream Out(buf);
1146 
1147  Out << "Calling ";
1148  describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
1149 
1150  assert(callEnter.asLocation().isValid());
1151  return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
1152 }
1153 
1154 std::shared_ptr<PathDiagnosticEventPiece>
1156  if (!callEnterWithin.asLocation().isValid())
1157  return nullptr;
1158  if (Callee->isImplicit() || !Callee->hasBody())
1159  return nullptr;
1160  if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
1161  if (MD->isDefaulted())
1162  return nullptr;
1163 
1164  SmallString<256> buf;
1165  llvm::raw_svector_ostream Out(buf);
1166 
1167  Out << "Entered call";
1168  describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
1169 
1170  return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
1171 }
1172 
1173 std::shared_ptr<PathDiagnosticEventPiece>
1175  // We do not produce call enters and call exits for autosynthesized property
1176  // accessors. We do generally produce them for other functions coming from
1177  // the body farm because they may call callbacks that bring us back into
1178  // visible code.
1179  if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
1180  return nullptr;
1181 
1182  SmallString<256> buf;
1183  llvm::raw_svector_ostream Out(buf);
1184 
1185  if (!CallStackMessage.empty()) {
1186  Out << CallStackMessage;
1187  } else {
1188  bool DidDescribe = describeCodeDecl(Out, Callee,
1189  /*ExtendedDescription=*/false,
1190  "Returning from ");
1191  if (!DidDescribe)
1192  Out << "Returning to caller";
1193  }
1194 
1195  assert(callReturn.asLocation().isValid());
1196  return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
1197 }
1198 
1199 static void compute_path_size(const PathPieces &pieces, unsigned &size) {
1200  for (const auto &I : pieces) {
1201  const PathDiagnosticPiece *piece = I.get();
1202  if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
1203  compute_path_size(cp->path, size);
1204  else
1205  ++size;
1206  }
1207 }
1208 
1210  unsigned size = 0;
1211  compute_path_size(path, size);
1212  return size;
1213 }
1214 
1215 //===----------------------------------------------------------------------===//
1216 // FoldingSet profiling methods.
1217 //===----------------------------------------------------------------------===//
1218 
1219 void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
1220  ID.AddInteger(Range.getBegin().getRawEncoding());
1221  ID.AddInteger(Range.getEnd().getRawEncoding());
1222  ID.AddInteger(Loc.getRawEncoding());
1223 }
1224 
1225 void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1226  ID.AddInteger((unsigned) getKind());
1227  ID.AddString(str);
1228  // FIXME: Add profiling support for code hints.
1229  ID.AddInteger((unsigned) getDisplayHint());
1230  ArrayRef<SourceRange> Ranges = getRanges();
1231  for (const auto &I : Ranges) {
1232  ID.AddInteger(I.getBegin().getRawEncoding());
1233  ID.AddInteger(I.getEnd().getRawEncoding());
1234  }
1235 }
1236 
1237 void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1239  for (const auto &I : path)
1240  ID.Add(*I);
1241 }
1242 
1243 void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1245  ID.Add(Pos);
1246 }
1247 
1248 void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1250  for (const auto &I : *this)
1251  ID.Add(I);
1252 }
1253 
1254 void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1256  for (const auto &I : subPieces)
1257  ID.Add(*I);
1258 }
1259 
1260 void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
1262 }
1263 
1264 void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
1265  ID.Add(getLocation());
1266  ID.AddString(BugType);
1267  ID.AddString(VerboseDesc);
1268  ID.AddString(Category);
1269 }
1270 
1271 void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1272  Profile(ID);
1273  for (const auto &I : path)
1274  ID.Add(*I);
1275  for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1276  ID.AddString(*I);
1277 }
1278 
1280 
1282  if (!N)
1283  return getMessageForSymbolNotFound();
1284 
1285  ProgramPoint P = N->getLocation();
1286  CallExitEnd CExit = P.castAs<CallExitEnd>();
1287 
1288  // FIXME: Use CallEvent to abstract this over all calls.
1289  const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
1290  const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
1291  if (!CE)
1292  return {};
1293 
1294  // Check if one of the parameters are set to the interesting symbol.
1295  unsigned ArgIndex = 0;
1296  for (CallExpr::const_arg_iterator I = CE->arg_begin(),
1297  E = CE->arg_end(); I != E; ++I, ++ArgIndex){
1298  SVal SV = N->getSVal(*I);
1299 
1300  // Check if the variable corresponding to the symbol is passed by value.
1301  SymbolRef AS = SV.getAsLocSymbol();
1302  if (AS == Sym) {
1303  return getMessageForArg(*I, ArgIndex);
1304  }
1305 
1306  // Check if the parameter is a pointer to the symbol.
1308  // Do not attempt to dereference void*.
1309  if ((*I)->getType()->isVoidPointerType())
1310  continue;
1311  SVal PSV = N->getState()->getSVal(Reg->getRegion());
1312  SymbolRef AS = PSV.getAsLocSymbol();
1313  if (AS == Sym) {
1314  return getMessageForArg(*I, ArgIndex);
1315  }
1316  }
1317  }
1318 
1319  // Check if we are returning the interesting symbol.
1320  SVal SV = N->getSVal(CE);
1321  SymbolRef RetSym = SV.getAsLocSymbol();
1322  if (RetSym == Sym) {
1323  return getMessageForReturn(CE);
1324  }
1325 
1326  return getMessageForSymbolNotFound();
1327 }
1328 
1330  unsigned ArgIndex) {
1331  // Printed parameters start at 1, not 0.
1332  ++ArgIndex;
1333 
1334  SmallString<200> buf;
1335  llvm::raw_svector_ostream os(buf);
1336 
1337  os << Msg << " via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1338  << " parameter";
1339 
1340  return os.str();
1341 }
1342 
1343 LLVM_DUMP_METHOD void PathPieces::dump() const {
1344  unsigned index = 0;
1345  for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
1346  llvm::errs() << "[" << index++ << "] ";
1347  (*I)->dump();
1348  llvm::errs() << "\n";
1349  }
1350 }
1351 
1352 LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const {
1353  llvm::errs() << "CALL\n--------------\n";
1354 
1355  if (const Stmt *SLoc = getLocation().getStmtOrNull())
1356  SLoc->dump();
1357  else if (const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee()))
1358  llvm::errs() << *ND << "\n";
1359  else
1360  getLocation().dump();
1361 }
1362 
1363 LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const {
1364  llvm::errs() << "EVENT\n--------------\n";
1365  llvm::errs() << getString() << "\n";
1366  llvm::errs() << " ---- at ----\n";
1367  getLocation().dump();
1368 }
1369 
1370 LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const {
1371  llvm::errs() << "CONTROL\n--------------\n";
1372  getStartLocation().dump();
1373  llvm::errs() << " ---- to ----\n";
1374  getEndLocation().dump();
1375 }
1376 
1377 LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
1378  llvm::errs() << "MACRO\n--------------\n";
1379  // FIXME: Print which macro is being invoked.
1380 }
1381 
1382 LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const {
1383  llvm::errs() << "NOTE\n--------------\n";
1384  llvm::errs() << getString() << "\n";
1385  llvm::errs() << " ---- at ----\n";
1386  getLocation().dump();
1387 }
1388 
1389 LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const {
1390  if (!isValid()) {
1391  llvm::errs() << "<INVALID>\n";
1392  return;
1393  }
1394 
1395  switch (K) {
1396  case RangeK:
1397  // FIXME: actually print the range.
1398  llvm::errs() << "<range>\n";
1399  break;
1400  case SingleLocK:
1401  asLocation().dump();
1402  llvm::errs() << "\n";
1403  break;
1404  case StmtK:
1405  if (S)
1406  S->dump();
1407  else
1408  llvm::errs() << "<NULL STMT>\n";
1409  break;
1410  case DeclK:
1411  if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
1412  llvm::errs() << *ND << "\n";
1413  else if (isa<BlockDecl>(D))
1414  // FIXME: Make this nicer.
1415  llvm::errs() << "<block>\n";
1416  else if (D)
1417  llvm::errs() << "<unknown decl>\n";
1418  else
1419  llvm::errs() << "<NULL DECL>\n";
1420  break;
1421  }
1422 }
SourceLocation getRBracLoc() const
Definition: Stmt.h:1334
Represents C++ allocator call.
Definition: CFG.h:240
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
Expr * getInit() const
Get the initializer.
Definition: DeclCXX.h:2454
static Optional< bool > compareMacro(const PathDiagnosticMacroPiece &X, const PathDiagnosticMacroPiece &Y)
const Stmt * getStmt() const
Definition: CFG.h:133
Stmt * getBody() const
Get the body of the Declaration.
ArrayRef< TemplateArgument > getPackAsArray() const
Return the array of arguments in this template argument pack.
Definition: TemplateBase.h:366
Defines the clang::FileManager interface and associated types.
static void compute_path_size(const PathPieces &pieces, unsigned &size)
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition: DeclBase.h:979
FullSourceLoc getExpansionLoc() const
Stmt - This represents one statement.
Definition: Stmt.h:66
C Language Family Type Representation.
Defines the SourceManager interface.
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:87
Represents a point when we begin processing an inlined call.
Definition: ProgramPoint.h:632
static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the beginning of the compound statement.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:410
Defines the C++ template declaration subclasses.
StringRef P
void Profile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, independent of the path it references.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
Represents C++ object destructor generated from a call to delete.
Definition: CFG.h:409
std::shared_ptr< PathDiagnosticEventPiece > getCallEnterWithinCallerEvent() const
virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex)
Produces the message of the following form: &#39;Msg via Nth parameter&#39;.
void Profile(llvm::FoldingSetNodeID &ID) const
A Range represents the closed range [from, to].
Represents a program point just before an implicit call event.
Definition: ProgramPoint.h:585
SourceLocation getEndLoc() const LLVM_READONLY
Definition: DeclBase.h:414
PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type...
Definition: CFG.h:99
const ProgramStateRef & getState() const
static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the end of the compound statement.
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
Definition: SVals.cpp:85
SourceLocation getColonLoc() const
Definition: Expr.h:3572
FileID getFileID() const
const Stmt * getTriggerStmt() const
Definition: CFG.h:394
Describes how types, statements, expressions, and declarations should be printed. ...
Definition: PrettyPrinter.h:38
static PathDiagnosticLocation createDeclEnd(const LocationContext *LC, const SourceManager &SM)
Constructs a location for the end of the enclosing declaration body.
Defines the clang::Expr interface and subclasses for C++ expressions.
static PathDiagnosticLocation createSingleLocation(const PathDiagnosticLocation &PDL)
Convert the given location into a single kind location.
Symbolic value.
Definition: SymExpr.h:30
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:270
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:288
AnalysisDeclContext contains the context data for the function or method under analysis.
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
Definition: CFG.h:384
static const LocationContext * findTopAutosynthesizedParentContext(const LocationContext *LC)
int Category
Definition: Format.cpp:1632
static bool isInCodeFile(SourceLocation SL, const SourceManager &SM)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:50
Optional< T > getLocationAs() const LLVM_LVALUE_FUNCTION
Represents a point when we start the call exit sequence (for inlined call).
Definition: ProgramPoint.h:670
bool isInvalid() const
static PathDiagnosticCallPiece * getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP, const SourceManager &SMgr)
BinaryOperatorKind
llvm::DOTGraphTraits< ExplodedGraph * > DefaultDOTGraphTraits const ExplodedNode const ExplodedNode *Out<< "\l\|";Out<< "StateID: ST"<< State-> NodeID
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
std::vector< std::pair< StringRef, StringRef > > ConsumerFiles
SourceLocation getLBracLoc() const
Definition: Stmt.h:1333
void Profile(llvm::FoldingSetNodeID &ID) const override
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
const LocationContext * getLocationContext() const
const LocationContext * getParent() const
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3287
std::string getMessage(const ExplodedNode *N) override
Search the call expression for the symbol Sym and dispatch the &#39;getMessageForX()&#39; methods to construc...
Represents a point after we ran remove dead bindings AFTER processing the given statement.
Definition: ProgramPoint.h:491
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
static Optional< bool > comparePath(const PathPieces &X, const PathPieces &Y)
virtual PathDiagnosticLocation getLocation() const =0
static SourceLocation getValidSourceLocation(const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEnd=false)
const CFGBlock * getCallSiteBlock() const
static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME, const SourceManager &SM)
For member expressions, return the location of the &#39;.
NodeId Parent
Definition: ASTDiff.cpp:192
CXXCtorInitializer * getInitializer() const
Definition: CFG.h:225
void print(const PrintingPolicy &Policy, raw_ostream &Out) const
Print this template argument to the given output stream.
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:3582
Const iterator for iterating over Stmt * arrays that contain only Expr *.
Definition: Stmt.h:997
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1241
const Stmt * getCallSite() const
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
Represents a single basic block in a source-level CFG.
Definition: CFG.h:552
PDFileEntry::ConsumerFiles * getFiles(const PathDiagnostic &PD)
Represents a point when we finish the call exit sequence (for inlined call).
Definition: ProgramPoint.h:690
DisplayHint getDisplayHint() const
getDisplayHint - Return a hint indicating where the diagnostic should be displayed by the PathDiagnos...
void FullProfile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, including its path.
This represents one expression.
Definition: Expr.h:106
Stmt * getTerminatorCondition(bool StripParens=true)
Definition: CFG.cpp:5467
static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y)
std::pair< FileID, unsigned > getDecomposedLoc() const
Decompose the specified location into a raw FileID + Offset pair.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
ExplodedNode * getFirstSucc()
const SourceManager & getManager() const
const SourceManager & getManager() const
static PathDiagnosticLocation getLocationForCaller(const StackFrameContext *SFC, const LocationContext *CallerCtx, const SourceManager &SM)
static const Stmt * getNextStmt(const ExplodedNode *N)
Retrieve the statement corresponding to the successor node.
static void describeTemplateParameters(raw_ostream &Out, const ArrayRef< TemplateArgument > TAList, const LangOptions &LO, StringRef Prefix=StringRef(), StringRef Postfix=StringRef())
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:2443
void resetDiagnosticLocationToMainFile()
If the last piece of the report point to the header file, resets the location of the report to be the...
bool isBodyAutosynthesized() const
Checks if the body of the Decl is generated by the BodyFarm.
SourceLocation getEnd() const
SourceLocation getMemberLoc() const
getMemberLoc - Return the location of the "member", in X->F, it is the location of &#39;F&#39;...
Definition: Expr.h:2879
const SourceManager & SM
Definition: Format.cpp:1490
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:112
static Optional< bool > comparePiece(const PathDiagnosticPiece &X, const PathDiagnosticPiece &Y)
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:301
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
static PathDiagnosticLocation createDeclBegin(const LocationContext *LC, const SourceManager &SM)
Create a location for the beginning of the enclosing declaration body.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
Kind getKind() const
Definition: CFG.h:119
std::shared_ptr< PathDiagnosticEventPiece > getCallEnterEvent() const
Kind
bool isBeforeInTranslationUnitThan(SourceLocation Loc) const
Determines the order of 2 source locations in the translation unit.
Encodes a location in the source.
SourceLocation getOperatorLoc() const
Definition: Expr.h:3319
StringRef getName() const
Definition: FileManager.h:86
std::shared_ptr< PathDiagnosticEventPiece > getCallExitEvent() const
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type...
Definition: ProgramPoint.h:142
void setCallee(const CallEnter &CE, const SourceManager &SM)
Cached information about one file (either on disk or in the virtual file system). ...
Definition: FileManager.h:60
std::deque< std::string >::const_iterator meta_iterator
static PathDiagnosticLocation createConditionalColonLoc(const ConditionalOperator *CO, const SourceManager &SM)
std::pair< bool, bool > isInTheSameTranslationUnit(std::pair< FileID, unsigned > &LOffs, std::pair< FileID, unsigned > &ROffs) const
Determines whether the two decomposed source location is in the same translation unit.
static bool describeCodeDecl(raw_ostream &Out, const Decl *D, bool ExtendedDescription, StringRef Prefix=StringRef())
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:76
static PathDiagnosticLocation createEnd(const Stmt *S, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)
Create a location for the end of the statement.
const Decl * getDecl() const
PathDiagnosticLocation getLocation() const override
SVal getSVal(const Stmt *S) const
Get the value of an arbitrary expression at this node.
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
Definition: CFG.h:110
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Represents a template argument.
Definition: TemplateBase.h:51
ConsumerFiles files
A vector of <consumer,file> pairs.
ArrayRef< SourceRange > getRanges() const
Return the SourceRanges associated with this PathDiagnosticPiece.
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
Represents a program point just after an implicit call event.
Definition: ProgramPoint.h:602
virtual void Profile(llvm::FoldingSetNodeID &ID) const
static void describeClass(raw_ostream &Out, const CXXRecordDecl *D, StringRef Prefix=StringRef())
const StackFrameContext * getCalleeContext() const
Definition: ProgramPoint.h:642
void FlushDiagnostics(FilesMade *FilesMade)
BinaryOperator::Opcode getOpcode(const SymExpr *SE)
const StackFrameContext * getCalleeContext() const
Definition: ProgramPoint.h:697
StmtClass getStmtClass() const
Definition: Stmt.h:1029
static Optional< bool > compareCall(const PathDiagnosticCallPiece &X, const PathDiagnosticCallPiece &Y)
void Profile(llvm::FoldingSetNodeID &ID) const override
const Decl * getDecl() const
const CXXDeleteExpr * getDeleteExpr() const
Definition: CFG.h:419
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
void dump() const
Dumps the specified AST fragment and all subtrees to llvm::errs().
Definition: ASTDumper.cpp:1622
static void describeTemplateParameter(raw_ostream &Out, const TemplateArgument &TArg, const LangOptions &LO)
const LocationContext * getLocationContext() const
Definition: ProgramPoint.h:181
void Profile(llvm::FoldingSetNodeID &ID) const override
static std::shared_ptr< PathDiagnosticCallPiece > construct(const CallExitEnd &CE, const SourceManager &SM)
A template argument list.
Definition: DeclTemplate.h:210
static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, const SourceManager &SM)
Create the location for the operator of the binary expression.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Definition: SemaDecl.cpp:13954
const CXXNewExpr * getAllocatorExpr() const
Definition: CFG.h:246
ArgKind getKind() const
Return the kind of stored template argument.
Definition: TemplateBase.h:235
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:2682
Defines the clang::SourceLocation class and associated facilities.
Represents a C++ struct/union/class.
Definition: DeclCXX.h:300
bool isValid() const
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
Create a location corresponding to the next valid ExplodedNode as end of path location.
Represents a top-level expression in a basic block.
Definition: CFG.h:56
static StringRef StripTrailingDots(StringRef s)
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:276
FullSourceLoc getSpellingLoc() const
A SourceLocation and its associated SourceManager.
void Profile(llvm::FoldingSetNodeID &ID) const override
void addDiagnostic(const PathDiagnostic &PD, StringRef ConsumerName, StringRef fileName)
Represents C++ base or member initializer from constructor&#39;s initialization list. ...
Definition: CFG.h:220
A trivial tuple used to represent a source range.
This represents a decl that may have a name.
Definition: Decl.h:249
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:153
AnalysisDeclContext * getAnalysisDeclContext() const
SourceLocation getBegin() const
static Optional< bool > compareControlFlow(const PathDiagnosticControlFlowPiece &X, const PathDiagnosticControlFlowPiece &Y)
This class handles loading and caching of source files into memory.
Represents C++ object destructor implicitly generated at the end of full expression for temporary obj...
Definition: CFG.h:477
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
Definition: DeclBase.cpp:906
SourceLocation getLocation() const
Definition: DeclBase.h:418
static bool compareCrossTUSourceLocs(FullSourceLoc XL, FullSourceLoc YL)
unsigned full_size()
Return the unrolled size of the path.
void Profile(llvm::FoldingSetNodeID &ID) const override