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