clang  8.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<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
727  return PathDiagnosticLocation(PIE->getLocation(), SMng);
728  } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
729  return getLocationForCaller(CE->getCalleeContext(),
730  CE->getLocationContext(),
731  SMng);
732  } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
733  return getLocationForCaller(CEE->getCalleeContext(),
734  CEE->getLocationContext(),
735  SMng);
736  } else if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
737  CFGElement BlockFront = BE->getBlock()->front();
738  if (auto StmtElt = BlockFront.getAs<CFGStmt>()) {
739  return PathDiagnosticLocation(StmtElt->getStmt()->getBeginLoc(), SMng);
740  } else if (auto NewAllocElt = BlockFront.getAs<CFGNewAllocator>()) {
741  return PathDiagnosticLocation(
742  NewAllocElt->getAllocatorExpr()->getBeginLoc(), SMng);
743  }
744  llvm_unreachable("Unexpected CFG element at front of block");
745  } else {
746  llvm_unreachable("Unexpected ProgramPoint");
747  }
748 
749  return PathDiagnosticLocation(S, SMng, P.getLocationContext());
750 }
751 
752 static const LocationContext *
755  const LocationContext *ParentLC = LC->getParent();
756  assert(ParentLC && "We don't start analysis from autosynthesized code");
757  while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
758  LC = ParentLC;
759  ParentLC = LC->getParent();
760  assert(ParentLC && "We don't start analysis from autosynthesized code");
761  }
762  return LC;
763 }
764 
766  // We cannot place diagnostics on autosynthesized code.
767  // Put them onto the call site through which we jumped into autosynthesized
768  // code for the first time.
769  const LocationContext *LC = N->getLocationContext();
771  // It must be a stack frame because we only autosynthesize functions.
772  return cast<StackFrameContext>(findTopAutosynthesizedParentContext(LC))
773  ->getCallSite();
774  }
775  // Otherwise, see if the node's program point directly points to a statement.
776  ProgramPoint P = N->getLocation();
777  if (auto SP = P.getAs<StmtPoint>())
778  return SP->getStmt();
779  if (auto BE = P.getAs<BlockEdge>())
780  return BE->getSrc()->getTerminator();
781  if (auto CE = P.getAs<CallEnter>())
782  return CE->getCallExpr();
783  if (auto CEE = P.getAs<CallExitEnd>())
784  return CEE->getCalleeContext()->getCallSite();
785  if (auto PIPP = P.getAs<PostInitializer>())
786  return PIPP->getInitializer()->getInit();
787  if (auto CEB = P.getAs<CallExitBegin>())
788  return CEB->getReturnStmt();
789  if (auto FEP = P.getAs<FunctionExitPoint>())
790  return FEP->getStmt();
791 
792  return nullptr;
793 }
794 
796  for (N = N->getFirstSucc(); N; N = N->getFirstSucc()) {
797  if (const Stmt *S = getStmt(N)) {
798  // Check if the statement is '?' or '&&'/'||'. These are "merges",
799  // not actual statement points.
800  switch (S->getStmtClass()) {
801  case Stmt::ChooseExprClass:
802  case Stmt::BinaryConditionalOperatorClass:
803  case Stmt::ConditionalOperatorClass:
804  continue;
805  case Stmt::BinaryOperatorClass: {
806  BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
807  if (Op == BO_LAnd || Op == BO_LOr)
808  continue;
809  break;
810  }
811  default:
812  break;
813  }
814  // We found the statement, so return it.
815  return S;
816  }
817  }
818 
819  return nullptr;
820 }
821 
824  const SourceManager &SM) {
825  assert(N && "Cannot create a location with a null node.");
826  const Stmt *S = getStmt(N);
827  const LocationContext *LC = N->getLocationContext();
828 
829  if (!S) {
830  // If this is an implicit call, return the implicit call point location.
832  return PathDiagnosticLocation(PIE->getLocation(), SM);
833  if (auto FE = N->getLocationAs<FunctionExitPoint>()) {
834  if (const ReturnStmt *RS = FE->getStmt())
835  return PathDiagnosticLocation::createBegin(RS, SM, LC);
836  }
837  S = getNextStmt(N);
838  }
839 
840  if (S) {
841  ProgramPoint P = N->getLocation();
842 
843  // For member expressions, return the location of the '.' or '->'.
844  if (const auto *ME = dyn_cast<MemberExpr>(S))
846 
847  // For binary operators, return the location of the operator.
848  if (const auto *B = dyn_cast<BinaryOperator>(S))
850 
852  return PathDiagnosticLocation::createEnd(S, SM, LC);
853 
854  if (S->getBeginLoc().isValid())
855  return PathDiagnosticLocation(S, SM, LC);
857  }
858 
859  return createDeclEnd(N->getLocationContext(), SM);
860 }
861 
863  const PathDiagnosticLocation &PDL) {
864  FullSourceLoc L = PDL.asLocation();
865  return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
866 }
867 
869  PathDiagnosticLocation::genLocation(SourceLocation L,
870  LocationOrAnalysisDeclContext LAC) const {
871  assert(isValid());
872  // Note that we want a 'switch' here so that the compiler can warn us in
873  // case we add more cases.
874  switch (K) {
875  case SingleLocK:
876  case RangeK:
877  break;
878  case StmtK:
879  // Defensive checking.
880  if (!S)
881  break;
882  return FullSourceLoc(getValidSourceLocation(S, LAC),
883  const_cast<SourceManager&>(*SM));
884  case DeclK:
885  // Defensive checking.
886  if (!D)
887  break;
888  return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
889  }
890 
891  return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
892 }
893 
895  PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
896  assert(isValid());
897  // Note that we want a 'switch' here so that the compiler can warn us in
898  // case we add more cases.
899  switch (K) {
900  case SingleLocK:
901  return PathDiagnosticRange(SourceRange(Loc,Loc), true);
902  case RangeK:
903  break;
904  case StmtK: {
905  const Stmt *S = asStmt();
906  switch (S->getStmtClass()) {
907  default:
908  break;
909  case Stmt::DeclStmtClass: {
910  const auto *DS = cast<DeclStmt>(S);
911  if (DS->isSingleDecl()) {
912  // Should always be the case, but we'll be defensive.
913  return SourceRange(DS->getBeginLoc(),
914  DS->getSingleDecl()->getLocation());
915  }
916  break;
917  }
918  // FIXME: Provide better range information for different
919  // terminators.
920  case Stmt::IfStmtClass:
921  case Stmt::WhileStmtClass:
922  case Stmt::DoStmtClass:
923  case Stmt::ForStmtClass:
924  case Stmt::ChooseExprClass:
925  case Stmt::IndirectGotoStmtClass:
926  case Stmt::SwitchStmtClass:
927  case Stmt::BinaryConditionalOperatorClass:
928  case Stmt::ConditionalOperatorClass:
929  case Stmt::ObjCForCollectionStmtClass: {
931  return SourceRange(L, L);
932  }
933  }
934  SourceRange R = S->getSourceRange();
935  if (R.isValid())
936  return R;
937  break;
938  }
939  case DeclK:
940  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
941  return MD->getSourceRange();
942  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
943  if (Stmt *Body = FD->getBody())
944  return Body->getSourceRange();
945  }
946  else {
947  SourceLocation L = D->getLocation();
948  return PathDiagnosticRange(SourceRange(L, L), true);
949  }
950  }
951 
952  return SourceRange(Loc, Loc);
953 }
954 
956  if (K == StmtK) {
957  K = RangeK;
958  S = nullptr;
959  D = nullptr;
960  }
961  else if (K == DeclK) {
962  K = SingleLocK;
963  S = nullptr;
964  D = nullptr;
965  }
966 }
967 
968 //===----------------------------------------------------------------------===//
969 // Manipulation of PathDiagnosticCallPieces.
970 //===----------------------------------------------------------------------===//
971 
972 std::shared_ptr<PathDiagnosticCallPiece>
974  const SourceManager &SM) {
975  const Decl *caller = CE.getLocationContext()->getDecl();
977  CE.getLocationContext(),
978  SM);
979  return std::shared_ptr<PathDiagnosticCallPiece>(
980  new PathDiagnosticCallPiece(caller, pos));
981 }
982 
985  const Decl *caller) {
986  std::shared_ptr<PathDiagnosticCallPiece> C(
987  new PathDiagnosticCallPiece(path, caller));
988  path.clear();
989  auto *R = C.get();
990  path.push_front(std::move(C));
991  return R;
992 }
993 
995  const SourceManager &SM) {
996  const StackFrameContext *CalleeCtx = CE.getCalleeContext();
997  Callee = CalleeCtx->getDecl();
998 
999  callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
1000  callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
1001 
1002  // Autosynthesized property accessors are special because we'd never
1003  // pop back up to non-autosynthesized code until we leave them.
1004  // This is not generally true for autosynthesized callees, which may call
1005  // non-autosynthesized callbacks.
1006  // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
1007  // defaults to false.
1008  if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
1009  IsCalleeAnAutosynthesizedPropertyAccessor = (
1010  MD->isPropertyAccessor() &&
1012 }
1013 
1014 static void describeTemplateParameters(raw_ostream &Out,
1015  const ArrayRef<TemplateArgument> TAList,
1016  const LangOptions &LO,
1017  StringRef Prefix = StringRef(),
1018  StringRef Postfix = StringRef());
1019 
1020 static void describeTemplateParameter(raw_ostream &Out,
1021  const TemplateArgument &TArg,
1022  const LangOptions &LO) {
1023 
1024  if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
1025  describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
1026  } else {
1027  TArg.print(PrintingPolicy(LO), Out);
1028  }
1029 }
1030 
1031 static void describeTemplateParameters(raw_ostream &Out,
1032  const ArrayRef<TemplateArgument> TAList,
1033  const LangOptions &LO,
1034  StringRef Prefix, StringRef Postfix) {
1035  if (TAList.empty())
1036  return;
1037 
1038  Out << Prefix;
1039  for (int I = 0, Last = TAList.size() - 1; I != Last; ++I) {
1040  describeTemplateParameter(Out, TAList[I], LO);
1041  Out << ", ";
1042  }
1043  describeTemplateParameter(Out, TAList[TAList.size() - 1], LO);
1044  Out << Postfix;
1045 }
1046 
1047 static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
1048  StringRef Prefix = StringRef()) {
1049  if (!D->getIdentifier())
1050  return;
1051  Out << Prefix << '\'' << *D;
1052  if (const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
1053  describeTemplateParameters(Out, T->getTemplateArgs().asArray(),
1054  D->getASTContext().getLangOpts(), "<", ">");
1055 
1056  Out << '\'';
1057 }
1058 
1059 static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
1060  bool ExtendedDescription,
1061  StringRef Prefix = StringRef()) {
1062  if (!D)
1063  return false;
1064 
1065  if (isa<BlockDecl>(D)) {
1066  if (ExtendedDescription)
1067  Out << Prefix << "anonymous block";
1068  return ExtendedDescription;
1069  }
1070 
1071  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
1072  Out << Prefix;
1073  if (ExtendedDescription && !MD->isUserProvided()) {
1074  if (MD->isExplicitlyDefaulted())
1075  Out << "defaulted ";
1076  else
1077  Out << "implicit ";
1078  }
1079 
1080  if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
1081  if (CD->isDefaultConstructor())
1082  Out << "default ";
1083  else if (CD->isCopyConstructor())
1084  Out << "copy ";
1085  else if (CD->isMoveConstructor())
1086  Out << "move ";
1087 
1088  Out << "constructor";
1089  describeClass(Out, MD->getParent(), " for ");
1090  } else if (isa<CXXDestructorDecl>(MD)) {
1091  if (!MD->isUserProvided()) {
1092  Out << "destructor";
1093  describeClass(Out, MD->getParent(), " for ");
1094  } else {
1095  // Use ~Foo for explicitly-written destructors.
1096  Out << "'" << *MD << "'";
1097  }
1098  } else if (MD->isCopyAssignmentOperator()) {
1099  Out << "copy assignment operator";
1100  describeClass(Out, MD->getParent(), " for ");
1101  } else if (MD->isMoveAssignmentOperator()) {
1102  Out << "move assignment operator";
1103  describeClass(Out, MD->getParent(), " for ");
1104  } else {
1105  if (MD->getParent()->getIdentifier())
1106  Out << "'" << *MD->getParent() << "::" << *MD << "'";
1107  else
1108  Out << "'" << *MD << "'";
1109  }
1110 
1111  return true;
1112  }
1113 
1114  Out << Prefix << '\'' << cast<NamedDecl>(*D);
1115 
1116  // Adding template parameters.
1117  if (const auto FD = dyn_cast<FunctionDecl>(D))
1118  if (const TemplateArgumentList *TAList =
1119  FD->getTemplateSpecializationArgs())
1120  describeTemplateParameters(Out, TAList->asArray(),
1121  FD->getASTContext().getLangOpts(), "<", ">");
1122 
1123  Out << '\'';
1124  return true;
1125 }
1126 
1127 std::shared_ptr<PathDiagnosticEventPiece>
1129  // We do not produce call enters and call exits for autosynthesized property
1130  // accessors. We do generally produce them for other functions coming from
1131  // the body farm because they may call callbacks that bring us back into
1132  // visible code.
1133  if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
1134  return nullptr;
1135 
1136  SmallString<256> buf;
1137  llvm::raw_svector_ostream Out(buf);
1138 
1139  Out << "Calling ";
1140  describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
1141 
1142  assert(callEnter.asLocation().isValid());
1143  return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
1144 }
1145 
1146 std::shared_ptr<PathDiagnosticEventPiece>
1148  if (!callEnterWithin.asLocation().isValid())
1149  return nullptr;
1150  if (Callee->isImplicit() || !Callee->hasBody())
1151  return nullptr;
1152  if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
1153  if (MD->isDefaulted())
1154  return nullptr;
1155 
1156  SmallString<256> buf;
1157  llvm::raw_svector_ostream Out(buf);
1158 
1159  Out << "Entered call";
1160  describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
1161 
1162  return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
1163 }
1164 
1165 std::shared_ptr<PathDiagnosticEventPiece>
1167  // We do not produce call enters and call exits for autosynthesized property
1168  // accessors. We do generally produce them for other functions coming from
1169  // the body farm because they may call callbacks that bring us back into
1170  // visible code.
1171  if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
1172  return nullptr;
1173 
1174  SmallString<256> buf;
1175  llvm::raw_svector_ostream Out(buf);
1176 
1177  if (!CallStackMessage.empty()) {
1178  Out << CallStackMessage;
1179  } else {
1180  bool DidDescribe = describeCodeDecl(Out, Callee,
1181  /*ExtendedDescription=*/false,
1182  "Returning from ");
1183  if (!DidDescribe)
1184  Out << "Returning to caller";
1185  }
1186 
1187  assert(callReturn.asLocation().isValid());
1188  return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
1189 }
1190 
1191 static void compute_path_size(const PathPieces &pieces, unsigned &size) {
1192  for (const auto &I : pieces) {
1193  const PathDiagnosticPiece *piece = I.get();
1194  if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
1195  compute_path_size(cp->path, size);
1196  else
1197  ++size;
1198  }
1199 }
1200 
1202  unsigned size = 0;
1203  compute_path_size(path, size);
1204  return size;
1205 }
1206 
1207 //===----------------------------------------------------------------------===//
1208 // FoldingSet profiling methods.
1209 //===----------------------------------------------------------------------===//
1210 
1211 void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
1212  ID.AddInteger(Range.getBegin().getRawEncoding());
1213  ID.AddInteger(Range.getEnd().getRawEncoding());
1214  ID.AddInteger(Loc.getRawEncoding());
1215 }
1216 
1217 void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1218  ID.AddInteger((unsigned) getKind());
1219  ID.AddString(str);
1220  // FIXME: Add profiling support for code hints.
1221  ID.AddInteger((unsigned) getDisplayHint());
1222  ArrayRef<SourceRange> Ranges = getRanges();
1223  for (const auto &I : Ranges) {
1224  ID.AddInteger(I.getBegin().getRawEncoding());
1225  ID.AddInteger(I.getEnd().getRawEncoding());
1226  }
1227 }
1228 
1229 void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1231  for (const auto &I : path)
1232  ID.Add(*I);
1233 }
1234 
1235 void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1237  ID.Add(Pos);
1238 }
1239 
1240 void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1242  for (const auto &I : *this)
1243  ID.Add(I);
1244 }
1245 
1246 void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1248  for (const auto &I : subPieces)
1249  ID.Add(*I);
1250 }
1251 
1252 void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
1254 }
1255 
1256 void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
1257  ID.Add(getLocation());
1258  ID.AddString(BugType);
1259  ID.AddString(VerboseDesc);
1260  ID.AddString(Category);
1261 }
1262 
1263 void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1264  Profile(ID);
1265  for (const auto &I : path)
1266  ID.Add(*I);
1267  for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1268  ID.AddString(*I);
1269 }
1270 
1272 
1274  if (!N)
1275  return getMessageForSymbolNotFound();
1276 
1277  ProgramPoint P = N->getLocation();
1278  CallExitEnd CExit = P.castAs<CallExitEnd>();
1279 
1280  // FIXME: Use CallEvent to abstract this over all calls.
1281  const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
1282  const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
1283  if (!CE)
1284  return {};
1285 
1286  // Check if one of the parameters are set to the interesting symbol.
1287  unsigned ArgIndex = 0;
1288  for (CallExpr::const_arg_iterator I = CE->arg_begin(),
1289  E = CE->arg_end(); I != E; ++I, ++ArgIndex){
1290  SVal SV = N->getSVal(*I);
1291 
1292  // Check if the variable corresponding to the symbol is passed by value.
1293  SymbolRef AS = SV.getAsLocSymbol();
1294  if (AS == Sym) {
1295  return getMessageForArg(*I, ArgIndex);
1296  }
1297 
1298  // Check if the parameter is a pointer to the symbol.
1300  // Do not attempt to dereference void*.
1301  if ((*I)->getType()->isVoidPointerType())
1302  continue;
1303  SVal PSV = N->getState()->getSVal(Reg->getRegion());
1304  SymbolRef AS = PSV.getAsLocSymbol();
1305  if (AS == Sym) {
1306  return getMessageForArg(*I, ArgIndex);
1307  }
1308  }
1309  }
1310 
1311  // Check if we are returning the interesting symbol.
1312  SVal SV = N->getSVal(CE);
1313  SymbolRef RetSym = SV.getAsLocSymbol();
1314  if (RetSym == Sym) {
1315  return getMessageForReturn(CE);
1316  }
1317 
1318  return getMessageForSymbolNotFound();
1319 }
1320 
1322  unsigned ArgIndex) {
1323  // Printed parameters start at 1, not 0.
1324  ++ArgIndex;
1325 
1326  SmallString<200> buf;
1327  llvm::raw_svector_ostream os(buf);
1328 
1329  os << Msg << " via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1330  << " parameter";
1331 
1332  return os.str();
1333 }
1334 
1335 LLVM_DUMP_METHOD void PathPieces::dump() const {
1336  unsigned index = 0;
1337  for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
1338  llvm::errs() << "[" << index++ << "] ";
1339  (*I)->dump();
1340  llvm::errs() << "\n";
1341  }
1342 }
1343 
1344 LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const {
1345  llvm::errs() << "CALL\n--------------\n";
1346 
1347  if (const Stmt *SLoc = getLocation().getStmtOrNull())
1348  SLoc->dump();
1349  else if (const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee()))
1350  llvm::errs() << *ND << "\n";
1351  else
1352  getLocation().dump();
1353 }
1354 
1355 LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const {
1356  llvm::errs() << "EVENT\n--------------\n";
1357  llvm::errs() << getString() << "\n";
1358  llvm::errs() << " ---- at ----\n";
1359  getLocation().dump();
1360 }
1361 
1362 LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const {
1363  llvm::errs() << "CONTROL\n--------------\n";
1364  getStartLocation().dump();
1365  llvm::errs() << " ---- to ----\n";
1366  getEndLocation().dump();
1367 }
1368 
1369 LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
1370  llvm::errs() << "MACRO\n--------------\n";
1371  // FIXME: Print which macro is being invoked.
1372 }
1373 
1374 LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const {
1375  llvm::errs() << "NOTE\n--------------\n";
1376  llvm::errs() << getString() << "\n";
1377  llvm::errs() << " ---- at ----\n";
1378  getLocation().dump();
1379 }
1380 
1381 LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const {
1382  if (!isValid()) {
1383  llvm::errs() << "<INVALID>\n";
1384  return;
1385  }
1386 
1387  switch (K) {
1388  case RangeK:
1389  // FIXME: actually print the range.
1390  llvm::errs() << "<range>\n";
1391  break;
1392  case SingleLocK:
1393  asLocation().dump();
1394  llvm::errs() << "\n";
1395  break;
1396  case StmtK:
1397  if (S)
1398  S->dump();
1399  else
1400  llvm::errs() << "<NULL STMT>\n";
1401  break;
1402  case DeclK:
1403  if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
1404  llvm::errs() << *ND << "\n";
1405  else if (isa<BlockDecl>(D))
1406  // FIXME: Make this nicer.
1407  llvm::errs() << "<block>\n";
1408  else if (D)
1409  llvm::errs() << "<unknown decl>\n";
1410  else
1411  llvm::errs() << "<NULL DECL>\n";
1412  break;
1413  }
1414 }
SourceLocation getRBracLoc() const
Definition: Stmt.h:1068
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:2448
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:3504
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:269
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:280
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:1067
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:3219
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:3514
Const iterator for iterating over Stmt * arrays that contain only Expr *.
Definition: Stmt.h:731
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:975
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:5462
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:2177
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:2784
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:293
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:3251
StringRef getName() const
Definition: FileManager.h:85
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:763
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:2860
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:13853
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:2587
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:268
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:248
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