clang  7.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 
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.
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>
310  if (XSL != YSL)
311  return XSL.isBeforeInTranslationUnitThan(YSL);
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 
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);
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 
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) {
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();
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  }
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  }
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->getLocEnd() : S->getLocStart();
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->getLocStart();
566  else
567  L = ADC->getDecl()->getLocEnd();
568  break;
569  }
570 
571  L = UseEnd ? Parent->getLocEnd() : Parent->getLocStart();
572  } while (!L.isValid());
573  }
574 
575  return L;
576 }
577 
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>();
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 
637  const SourceManager &SM) {
638  return PathDiagnosticLocation(D->getLocStart(), 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())->getLocStart();
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()->getLocStart(), SMng);
740  } else if (auto NewAllocElt = BlockFront.getAs<CFGNewAllocator>()) {
741  return PathDiagnosticLocation(
742  NewAllocElt->getAllocatorExpr()->getLocStart(), 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 (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
778  return SP->getStmt();
779  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>())
780  return BE->getSrc()->getTerminator();
781  if (Optional<CallEnter> CE = P.getAs<CallEnter>())
782  return CE->getCallExpr();
783  if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>())
784  return CEE->getCalleeContext()->getCallSite();
786  return PIPP->getInitializer()->getInit();
788  return CEB->getReturnStmt();
789 
790  return nullptr;
791 }
792 
794  for (N = N->getFirstSucc(); N; N = N->getFirstSucc()) {
795  if (const Stmt *S = getStmt(N)) {
796  // Check if the statement is '?' or '&&'/'||'. These are "merges",
797  // not actual statement points.
798  switch (S->getStmtClass()) {
799  case Stmt::ChooseExprClass:
800  case Stmt::BinaryConditionalOperatorClass:
801  case Stmt::ConditionalOperatorClass:
802  continue;
803  case Stmt::BinaryOperatorClass: {
804  BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
805  if (Op == BO_LAnd || Op == BO_LOr)
806  continue;
807  break;
808  }
809  default:
810  break;
811  }
812  // We found the statement, so return it.
813  return S;
814  }
815  }
816 
817  return nullptr;
818 }
819 
822  const SourceManager &SM) {
823  assert(N && "Cannot create a location with a null node.");
824  const Stmt *S = getStmt(N);
825 
826  if (!S) {
827  // If this is an implicit call, return the implicit call point location.
829  return PathDiagnosticLocation(PIE->getLocation(), SM);
830  S = getNextStmt(N);
831  }
832 
833  if (S) {
834  ProgramPoint P = N->getLocation();
835  const LocationContext *LC = N->getLocationContext();
836 
837  // For member expressions, return the location of the '.' or '->'.
838  if (const auto *ME = dyn_cast<MemberExpr>(S))
840 
841  // For binary operators, return the location of the operator.
842  if (const auto *B = dyn_cast<BinaryOperator>(S))
844 
846  return PathDiagnosticLocation::createEnd(S, SM, LC);
847 
848  if (S->getLocStart().isValid())
849  return PathDiagnosticLocation(S, SM, LC);
851  }
852 
853  return createDeclEnd(N->getLocationContext(), SM);
854 }
855 
857  const PathDiagnosticLocation &PDL) {
858  FullSourceLoc L = PDL.asLocation();
859  return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
860 }
861 
863  PathDiagnosticLocation::genLocation(SourceLocation L,
864  LocationOrAnalysisDeclContext LAC) const {
865  assert(isValid());
866  // Note that we want a 'switch' here so that the compiler can warn us in
867  // case we add more cases.
868  switch (K) {
869  case SingleLocK:
870  case RangeK:
871  break;
872  case StmtK:
873  // Defensive checking.
874  if (!S)
875  break;
876  return FullSourceLoc(getValidSourceLocation(S, LAC),
877  const_cast<SourceManager&>(*SM));
878  case DeclK:
879  // Defensive checking.
880  if (!D)
881  break;
882  return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
883  }
884 
885  return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
886 }
887 
889  PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
890  assert(isValid());
891  // Note that we want a 'switch' here so that the compiler can warn us in
892  // case we add more cases.
893  switch (K) {
894  case SingleLocK:
895  return PathDiagnosticRange(SourceRange(Loc,Loc), true);
896  case RangeK:
897  break;
898  case StmtK: {
899  const Stmt *S = asStmt();
900  switch (S->getStmtClass()) {
901  default:
902  break;
903  case Stmt::DeclStmtClass: {
904  const auto *DS = cast<DeclStmt>(S);
905  if (DS->isSingleDecl()) {
906  // Should always be the case, but we'll be defensive.
907  return SourceRange(DS->getLocStart(),
908  DS->getSingleDecl()->getLocation());
909  }
910  break;
911  }
912  // FIXME: Provide better range information for different
913  // terminators.
914  case Stmt::IfStmtClass:
915  case Stmt::WhileStmtClass:
916  case Stmt::DoStmtClass:
917  case Stmt::ForStmtClass:
918  case Stmt::ChooseExprClass:
919  case Stmt::IndirectGotoStmtClass:
920  case Stmt::SwitchStmtClass:
921  case Stmt::BinaryConditionalOperatorClass:
922  case Stmt::ConditionalOperatorClass:
923  case Stmt::ObjCForCollectionStmtClass: {
925  return SourceRange(L, L);
926  }
927  }
928  SourceRange R = S->getSourceRange();
929  if (R.isValid())
930  return R;
931  break;
932  }
933  case DeclK:
934  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
935  return MD->getSourceRange();
936  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
937  if (Stmt *Body = FD->getBody())
938  return Body->getSourceRange();
939  }
940  else {
941  SourceLocation L = D->getLocation();
942  return PathDiagnosticRange(SourceRange(L, L), true);
943  }
944  }
945 
946  return SourceRange(Loc, Loc);
947 }
948 
950  if (K == StmtK) {
951  K = RangeK;
952  S = nullptr;
953  D = nullptr;
954  }
955  else if (K == DeclK) {
956  K = SingleLocK;
957  S = nullptr;
958  D = nullptr;
959  }
960 }
961 
962 //===----------------------------------------------------------------------===//
963 // Manipulation of PathDiagnosticCallPieces.
964 //===----------------------------------------------------------------------===//
965 
966 std::shared_ptr<PathDiagnosticCallPiece>
968  const SourceManager &SM) {
969  const Decl *caller = CE.getLocationContext()->getDecl();
971  CE.getLocationContext(),
972  SM);
973  return std::shared_ptr<PathDiagnosticCallPiece>(
974  new PathDiagnosticCallPiece(caller, pos));
975 }
976 
979  const Decl *caller) {
980  std::shared_ptr<PathDiagnosticCallPiece> C(
981  new PathDiagnosticCallPiece(path, caller));
982  path.clear();
983  auto *R = C.get();
984  path.push_front(std::move(C));
985  return R;
986 }
987 
989  const SourceManager &SM) {
990  const StackFrameContext *CalleeCtx = CE.getCalleeContext();
991  Callee = CalleeCtx->getDecl();
992 
993  callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
994  callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
995 
996  // Autosynthesized property accessors are special because we'd never
997  // pop back up to non-autosynthesized code until we leave them.
998  // This is not generally true for autosynthesized callees, which may call
999  // non-autosynthesized callbacks.
1000  // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
1001  // defaults to false.
1002  if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
1003  IsCalleeAnAutosynthesizedPropertyAccessor = (
1004  MD->isPropertyAccessor() &&
1006 }
1007 
1008 static void describeTemplateParameters(raw_ostream &Out,
1009  const ArrayRef<TemplateArgument> TAList,
1010  const LangOptions &LO,
1011  StringRef Prefix = StringRef(),
1012  StringRef Postfix = StringRef());
1013 
1014 static void describeTemplateParameter(raw_ostream &Out,
1015  const TemplateArgument &TArg,
1016  const LangOptions &LO) {
1017 
1018  if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
1019  describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
1020  } else {
1021  TArg.print(PrintingPolicy(LO), Out);
1022  }
1023 }
1024 
1025 static void describeTemplateParameters(raw_ostream &Out,
1026  const ArrayRef<TemplateArgument> TAList,
1027  const LangOptions &LO,
1028  StringRef Prefix, StringRef Postfix) {
1029  if (TAList.empty())
1030  return;
1031 
1032  Out << Prefix;
1033  for (int I = 0, Last = TAList.size() - 1; I != Last; ++I) {
1034  describeTemplateParameter(Out, TAList[I], LO);
1035  Out << ", ";
1036  }
1037  describeTemplateParameter(Out, TAList[TAList.size() - 1], LO);
1038  Out << Postfix;
1039 }
1040 
1041 static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
1042  StringRef Prefix = StringRef()) {
1043  if (!D->getIdentifier())
1044  return;
1045  Out << Prefix << '\'' << *D;
1046  if (const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
1047  describeTemplateParameters(Out, T->getTemplateArgs().asArray(),
1048  D->getASTContext().getLangOpts(), "<", ">");
1049 
1050  Out << '\'';
1051 }
1052 
1053 static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
1054  bool ExtendedDescription,
1055  StringRef Prefix = StringRef()) {
1056  if (!D)
1057  return false;
1058 
1059  if (isa<BlockDecl>(D)) {
1060  if (ExtendedDescription)
1061  Out << Prefix << "anonymous block";
1062  return ExtendedDescription;
1063  }
1064 
1065  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
1066  Out << Prefix;
1067  if (ExtendedDescription && !MD->isUserProvided()) {
1068  if (MD->isExplicitlyDefaulted())
1069  Out << "defaulted ";
1070  else
1071  Out << "implicit ";
1072  }
1073 
1074  if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
1075  if (CD->isDefaultConstructor())
1076  Out << "default ";
1077  else if (CD->isCopyConstructor())
1078  Out << "copy ";
1079  else if (CD->isMoveConstructor())
1080  Out << "move ";
1081 
1082  Out << "constructor";
1083  describeClass(Out, MD->getParent(), " for ");
1084  } else if (isa<CXXDestructorDecl>(MD)) {
1085  if (!MD->isUserProvided()) {
1086  Out << "destructor";
1087  describeClass(Out, MD->getParent(), " for ");
1088  } else {
1089  // Use ~Foo for explicitly-written destructors.
1090  Out << "'" << *MD << "'";
1091  }
1092  } else if (MD->isCopyAssignmentOperator()) {
1093  Out << "copy assignment operator";
1094  describeClass(Out, MD->getParent(), " for ");
1095  } else if (MD->isMoveAssignmentOperator()) {
1096  Out << "move assignment operator";
1097  describeClass(Out, MD->getParent(), " for ");
1098  } else {
1099  if (MD->getParent()->getIdentifier())
1100  Out << "'" << *MD->getParent() << "::" << *MD << "'";
1101  else
1102  Out << "'" << *MD << "'";
1103  }
1104 
1105  return true;
1106  }
1107 
1108  Out << Prefix << '\'' << cast<NamedDecl>(*D);
1109 
1110  // Adding template parameters.
1111  if (const auto FD = dyn_cast<FunctionDecl>(D))
1112  if (const TemplateArgumentList *TAList =
1113  FD->getTemplateSpecializationArgs())
1114  describeTemplateParameters(Out, TAList->asArray(),
1115  FD->getASTContext().getLangOpts(), "<", ">");
1116 
1117  Out << '\'';
1118  return true;
1119 }
1120 
1121 std::shared_ptr<PathDiagnosticEventPiece>
1123  // We do not produce call enters and call exits for autosynthesized property
1124  // accessors. We do generally produce them for other functions coming from
1125  // the body farm because they may call callbacks that bring us back into
1126  // visible code.
1127  if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
1128  return nullptr;
1129 
1130  SmallString<256> buf;
1131  llvm::raw_svector_ostream Out(buf);
1132 
1133  Out << "Calling ";
1134  describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
1135 
1136  assert(callEnter.asLocation().isValid());
1137  return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
1138 }
1139 
1140 std::shared_ptr<PathDiagnosticEventPiece>
1142  if (!callEnterWithin.asLocation().isValid())
1143  return nullptr;
1144  if (Callee->isImplicit() || !Callee->hasBody())
1145  return nullptr;
1146  if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
1147  if (MD->isDefaulted())
1148  return nullptr;
1149 
1150  SmallString<256> buf;
1151  llvm::raw_svector_ostream Out(buf);
1152 
1153  Out << "Entered call";
1154  describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
1155 
1156  return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
1157 }
1158 
1159 std::shared_ptr<PathDiagnosticEventPiece>
1161  // We do not produce call enters and call exits for autosynthesized property
1162  // accessors. We do generally produce them for other functions coming from
1163  // the body farm because they may call callbacks that bring us back into
1164  // visible code.
1165  if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
1166  return nullptr;
1167 
1168  SmallString<256> buf;
1169  llvm::raw_svector_ostream Out(buf);
1170 
1171  if (!CallStackMessage.empty()) {
1172  Out << CallStackMessage;
1173  } else {
1174  bool DidDescribe = describeCodeDecl(Out, Callee,
1175  /*ExtendedDescription=*/false,
1176  "Returning from ");
1177  if (!DidDescribe)
1178  Out << "Returning to caller";
1179  }
1180 
1181  assert(callReturn.asLocation().isValid());
1182  return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
1183 }
1184 
1185 static void compute_path_size(const PathPieces &pieces, unsigned &size) {
1186  for (const auto &I : pieces) {
1187  const PathDiagnosticPiece *piece = I.get();
1188  if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
1189  compute_path_size(cp->path, size);
1190  else
1191  ++size;
1192  }
1193 }
1194 
1196  unsigned size = 0;
1197  compute_path_size(path, size);
1198  return size;
1199 }
1200 
1201 //===----------------------------------------------------------------------===//
1202 // FoldingSet profiling methods.
1203 //===----------------------------------------------------------------------===//
1204 
1205 void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
1206  ID.AddInteger(Range.getBegin().getRawEncoding());
1207  ID.AddInteger(Range.getEnd().getRawEncoding());
1208  ID.AddInteger(Loc.getRawEncoding());
1209 }
1210 
1211 void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1212  ID.AddInteger((unsigned) getKind());
1213  ID.AddString(str);
1214  // FIXME: Add profiling support for code hints.
1215  ID.AddInteger((unsigned) getDisplayHint());
1216  ArrayRef<SourceRange> Ranges = getRanges();
1217  for (const auto &I : Ranges) {
1218  ID.AddInteger(I.getBegin().getRawEncoding());
1219  ID.AddInteger(I.getEnd().getRawEncoding());
1220  }
1221 }
1222 
1223 void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1225  for (const auto &I : path)
1226  ID.Add(*I);
1227 }
1228 
1229 void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1231  ID.Add(Pos);
1232 }
1233 
1234 void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1236  for (const auto &I : *this)
1237  ID.Add(I);
1238 }
1239 
1240 void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1242  for (const auto &I : subPieces)
1243  ID.Add(*I);
1244 }
1245 
1246 void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
1248 }
1249 
1250 void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
1251  ID.Add(getLocation());
1252  ID.AddString(BugType);
1253  ID.AddString(VerboseDesc);
1254  ID.AddString(Category);
1255 }
1256 
1257 void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1258  Profile(ID);
1259  for (const auto &I : path)
1260  ID.Add(*I);
1261  for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1262  ID.AddString(*I);
1263 }
1264 
1266 
1268  if (!N)
1269  return getMessageForSymbolNotFound();
1270 
1271  ProgramPoint P = N->getLocation();
1272  CallExitEnd CExit = P.castAs<CallExitEnd>();
1273 
1274  // FIXME: Use CallEvent to abstract this over all calls.
1275  const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
1276  const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
1277  if (!CE)
1278  return {};
1279 
1280  // Check if one of the parameters are set to the interesting symbol.
1281  unsigned ArgIndex = 0;
1282  for (CallExpr::const_arg_iterator I = CE->arg_begin(),
1283  E = CE->arg_end(); I != E; ++I, ++ArgIndex){
1284  SVal SV = N->getSVal(*I);
1285 
1286  // Check if the variable corresponding to the symbol is passed by value.
1287  SymbolRef AS = SV.getAsLocSymbol();
1288  if (AS == Sym) {
1289  return getMessageForArg(*I, ArgIndex);
1290  }
1291 
1292  // Check if the parameter is a pointer to the symbol.
1294  // Do not attempt to dereference void*.
1295  if ((*I)->getType()->isVoidPointerType())
1296  continue;
1297  SVal PSV = N->getState()->getSVal(Reg->getRegion());
1298  SymbolRef AS = PSV.getAsLocSymbol();
1299  if (AS == Sym) {
1300  return getMessageForArg(*I, ArgIndex);
1301  }
1302  }
1303  }
1304 
1305  // Check if we are returning the interesting symbol.
1306  SVal SV = N->getSVal(CE);
1307  SymbolRef RetSym = SV.getAsLocSymbol();
1308  if (RetSym == Sym) {
1309  return getMessageForReturn(CE);
1310  }
1311 
1312  return getMessageForSymbolNotFound();
1313 }
1314 
1316  unsigned ArgIndex) {
1317  // Printed parameters start at 1, not 0.
1318  ++ArgIndex;
1319 
1320  SmallString<200> buf;
1321  llvm::raw_svector_ostream os(buf);
1322 
1323  os << Msg << " via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1324  << " parameter";
1325 
1326  return os.str();
1327 }
1328 
1329 LLVM_DUMP_METHOD void PathPieces::dump() const {
1330  unsigned index = 0;
1331  for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
1332  llvm::errs() << "[" << index++ << "] ";
1333  (*I)->dump();
1334  llvm::errs() << "\n";
1335  }
1336 }
1337 
1338 LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const {
1339  llvm::errs() << "CALL\n--------------\n";
1340 
1341  if (const Stmt *SLoc = getLocation().getStmtOrNull())
1342  SLoc->dump();
1343  else if (const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee()))
1344  llvm::errs() << *ND << "\n";
1345  else
1346  getLocation().dump();
1347 }
1348 
1349 LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const {
1350  llvm::errs() << "EVENT\n--------------\n";
1351  llvm::errs() << getString() << "\n";
1352  llvm::errs() << " ---- at ----\n";
1353  getLocation().dump();
1354 }
1355 
1356 LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const {
1357  llvm::errs() << "CONTROL\n--------------\n";
1358  getStartLocation().dump();
1359  llvm::errs() << " ---- to ----\n";
1360  getEndLocation().dump();
1361 }
1362 
1363 LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
1364  llvm::errs() << "MACRO\n--------------\n";
1365  // FIXME: Print which macro is being invoked.
1366 }
1367 
1368 LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const {
1369  llvm::errs() << "NOTE\n--------------\n";
1370  llvm::errs() << getString() << "\n";
1371  llvm::errs() << " ---- at ----\n";
1372  getLocation().dump();
1373 }
1374 
1375 LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const {
1376  if (!isValid()) {
1377  llvm::errs() << "<INVALID>\n";
1378  return;
1379  }
1380 
1381  switch (K) {
1382  case RangeK:
1383  // FIXME: actually print the range.
1384  llvm::errs() << "<range>\n";
1385  break;
1386  case SingleLocK:
1387  asLocation().dump();
1388  llvm::errs() << "\n";
1389  break;
1390  case StmtK:
1391  if (S)
1392  S->dump();
1393  else
1394  llvm::errs() << "<NULL STMT>\n";
1395  break;
1396  case DeclK:
1397  if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
1398  llvm::errs() << *ND << "\n";
1399  else if (isa<BlockDecl>(D))
1400  // FIXME: Make this nicer.
1401  llvm::errs() << "<block>\n";
1402  else if (D)
1403  llvm::errs() << "<unknown decl>\n";
1404  else
1405  llvm::errs() << "<NULL DECL>\n";
1406  break;
1407  }
1408 }
SourceLocation getRBracLoc() const
Definition: Stmt.h:700
CFGNewAllocator - Represents C++ allocator call.
Definition: CFG.h:235
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:2445
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: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:984
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:86
Represents a point when we begin processing an inlined call.
Definition: ProgramPoint.h:604
static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the beginning of the compound statement.
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.
CFGDeleteDtor - Represents C++ object destructor generated from a call to delete. ...
Definition: CFG.h:405
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:557
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type...
Definition: CFG.h:98
SourceLocation getLocEnd() const LLVM_READONLY
Definition: DeclBase.h:413
const ProgramStateRef & getState() const
static std::shared_ptr< PathDiagnosticCallPiece > construct(const ExplodedNode *N, const CallExitEnd &CE, const SourceManager &SM)
PathDiagnosticLocation getStartLocation() 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:3343
meta_iterator meta_begin() const
FileID getFileID() const
const Stmt * getTriggerStmt() const
Definition: CFG.h:389
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.
PathDiagnosticLocation getLocation() const
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
AnalysisDeclContext contains the context data for the function or method under analysis.
CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated for automatic object or t...
Definition: CFG.h:379
Definition: Format.h:2031
StringRef getVerboseDescription() const
static const LocationContext * findTopAutosynthesizedParentContext(const LocationContext *LC)
int Category
Definition: Format.cpp:1607
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:642
bool isInvalid() const
static PathDiagnosticCallPiece * getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP, const SourceManager &SMgr)
BinaryOperatorKind
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:699
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:3069
std::string getMessage(const ExplodedNode *N) override
Search the call expression for the symbol Sym and dispatch the &#39;getMessageForX()&#39; methods to construc...
StringRef getBugType() const
meta_iterator meta_end() const
Represents a point after we ran remove dead bindings AFTER processing the given statement.
Definition: ProgramPoint.h:463
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
PathDiagnosticLocation getEndLocation() const
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:220
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:3353
Const iterator for iterating over Stmt * arrays that contain only Expr *.
Definition: Stmt.h:357
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:609
const Stmt * getCallSite() const
SourceLocation getLocEnd() const LLVM_READONLY
Definition: Stmt.cpp:291
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
CFGBlock - Represents a single basic block in a source-level CFG.
Definition: CFG.h:548
PDFileEntry::ConsumerFiles * getFiles(const PathDiagnostic &PD)
Represents a point when we finish the call exit sequence (for inlined call).
Definition: ProgramPoint.h:662
void FullProfile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, including its path.
Expr - This represents one expression.
Definition: Expr.h:106
Stmt * getTerminatorCondition(bool StripParens=true)
Definition: CFG.cpp:5376
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.
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
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:2665
const SourceManager & SM
Definition: Format.cpp:1474
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
StringRef getCategory() const
static Optional< bool > comparePiece(const PathDiagnosticPiece &X, const PathDiagnosticPiece &Y)
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
SourceLocation getLocStart() const LLVM_READONLY
Definition: DeclBase.h:409
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
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:3107
StringRef getName() const
Definition: FileManager.h:84
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:141
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: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
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: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:574
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:614
void FlushDiagnostics(FilesMade *FilesMade)
BinaryOperator::Opcode getOpcode(const SymExpr *SE)
const StackFrameContext * getCalleeContext() const
Definition: ProgramPoint.h:669
const ExplodedNode * getFirstSucc() const
StmtClass getStmtClass() const
Definition: Stmt.h:389
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:415
void appendToDesc(StringRef S)
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
static void describeTemplateParameter(raw_ostream &Out, const TemplateArgument &TArg, const LangOptions &LO)
const LocationContext * getLocationContext() const
Definition: ProgramPoint.h:180
void Profile(llvm::FoldingSetNodeID &ID) const override
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:13719
const CXXNewExpr * getAllocatorExpr() const
Definition: CFG.h:241
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:2465
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.
CFGElement - 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:266
FullSourceLoc getSpellingLoc() const
A SourceLocation and its associated SourceManager.
PathDiagnosticLocation callEnterWithin
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:930
void Profile(llvm::FoldingSetNodeID &ID) const override
void addDiagnostic(const PathDiagnostic &PD, StringRef ConsumerName, StringRef fileName)
CFGInitializer - Represents C++ base or member initializer from constructor&#39;s initialization list...
Definition: CFG.h:215
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:152
AnalysisDeclContext * getAnalysisDeclContext() const
SourceLocation getLocStart() const LLVM_READONLY
Definition: Stmt.cpp:278
SourceLocation getBegin() const
static Optional< bool > compareControlFlow(const PathDiagnosticControlFlowPiece &X, const PathDiagnosticControlFlowPiece &Y)
This class handles loading and caching of source files into memory.
CFGTemporaryDtor - Represents C++ object destructor implicitly generated at the end of full expressio...
Definition: CFG.h:473
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
Definition: DeclBase.cpp:882
SourceLocation getLocation() const
Definition: DeclBase.h:417
static bool compareCrossTUSourceLocs(FullSourceLoc XL, FullSourceLoc YL)
unsigned full_size()
Return the unrolled size of the path.
void Profile(llvm::FoldingSetNodeID &ID) const override
StringRef getShortDescription() const
const Decl * getDeclWithIssue() const
Return the semantic context where an issue occurred.