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.getFileID());
410  const FileEntry *YFE = SM.getFileEntryForID(YL.getFileID());
411  if (!XFE || !YFE)
412  return XFE && !YFE;
413  return XFE->getName() < YFE->getName();
414 }
415 
416 static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
419  if (XL != YL)
420  return compareCrossTUSourceLocs(XL, YL);
421  if (X.getBugType() != Y.getBugType())
422  return X.getBugType() < Y.getBugType();
423  if (X.getCategory() != Y.getCategory())
424  return X.getCategory() < Y.getCategory();
428  return X.getShortDescription() < Y.getShortDescription();
429  if (X.getDeclWithIssue() != Y.getDeclWithIssue()) {
430  const Decl *XD = X.getDeclWithIssue();
431  if (!XD)
432  return true;
433  const Decl *YD = Y.getDeclWithIssue();
434  if (!YD)
435  return false;
436  SourceLocation XDL = XD->getLocation();
437  SourceLocation YDL = YD->getLocation();
438  if (XDL != YDL) {
439  const SourceManager &SM = XL.getManager();
440  return compareCrossTUSourceLocs(FullSourceLoc(XDL, SM),
441  FullSourceLoc(YDL, SM));
442  }
443  }
446  if (XE - XI != YE - YI)
447  return (XE - XI) < (YE - YI);
448  for ( ; XI != XE ; ++XI, ++YI) {
449  if (*XI != *YI)
450  return (*XI) < (*YI);
451  }
453  assert(b.hasValue());
454  return b.getValue();
455 }
456 
459  if (flushed)
460  return;
461 
462  flushed = true;
463 
464  std::vector<const PathDiagnostic *> BatchDiags;
465  for (const auto &D : Diags)
466  BatchDiags.push_back(&D);
467 
468  // Sort the diagnostics so that they are always emitted in a deterministic
469  // order.
470  int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
471  [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
472  assert(*X != *Y && "PathDiagnostics not uniqued!");
473  if (compare(**X, **Y))
474  return -1;
475  assert(compare(**Y, **X) && "Not a total order!");
476  return 1;
477  };
478  array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
479 
480  FlushDiagnosticsImpl(BatchDiags, Files);
481 
482  // Delete the flushed diagnostics.
483  for (const auto D : BatchDiags)
484  delete D;
485 
486  // Clear out the FoldingSet.
487  Diags.clear();
488 }
489 
491  for (PDFileEntry &Entry : Set)
492  Entry.~PDFileEntry();
493 }
494 
496  StringRef ConsumerName,
497  StringRef FileName) {
498  llvm::FoldingSetNodeID NodeID;
499  NodeID.Add(PD);
500  void *InsertPos;
501  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
502  if (!Entry) {
503  Entry = Alloc.Allocate<PDFileEntry>();
504  Entry = new (Entry) PDFileEntry(NodeID);
505  Set.InsertNode(Entry, InsertPos);
506  }
507 
508  // Allocate persistent storage for the file name.
509  char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
510  memcpy(FileName_cstr, FileName.data(), FileName.size());
511 
512  Entry->files.push_back(std::make_pair(ConsumerName,
513  StringRef(FileName_cstr,
514  FileName.size())));
515 }
516 
519  llvm::FoldingSetNodeID NodeID;
520  NodeID.Add(PD);
521  void *InsertPos;
522  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
523  if (!Entry)
524  return nullptr;
525  return &Entry->files;
526 }
527 
528 //===----------------------------------------------------------------------===//
529 // PathDiagnosticLocation methods.
530 //===----------------------------------------------------------------------===//
531 
534  bool UseEnd = false) {
535  SourceLocation L = UseEnd ? S->getLocEnd() : S->getLocStart();
536  assert(!LAC.isNull() && "A valid LocationContext or AnalysisDeclContext should "
537  "be passed to PathDiagnosticLocation upon creation.");
538 
539  // S might be a temporary statement that does not have a location in the
540  // source code, so find an enclosing statement and use its location.
541  if (!L.isValid()) {
542  AnalysisDeclContext *ADC;
543  if (LAC.is<const LocationContext*>())
544  ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext();
545  else
546  ADC = LAC.get<AnalysisDeclContext*>();
547 
548  ParentMap &PM = ADC->getParentMap();
549 
550  const Stmt *Parent = S;
551  do {
552  Parent = PM.getParent(Parent);
553 
554  // In rare cases, we have implicit top-level expressions,
555  // such as arguments for implicit member initializers.
556  // In this case, fall back to the start of the body (even if we were
557  // asked for the statement end location).
558  if (!Parent) {
559  const Stmt *Body = ADC->getBody();
560  if (Body)
561  L = Body->getLocStart();
562  else
563  L = ADC->getDecl()->getLocEnd();
564  break;
565  }
566 
567  L = UseEnd ? Parent->getLocEnd() : Parent->getLocStart();
568  } while (!L.isValid());
569  }
570 
571  return L;
572 }
573 
576  const LocationContext *CallerCtx,
577  const SourceManager &SM) {
578  const CFGBlock &Block = *SFC->getCallSiteBlock();
579  CFGElement Source = Block[SFC->getIndex()];
580 
581  switch (Source.getKind()) {
585  return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
586  SM, CallerCtx);
588  const CFGInitializer &Init = Source.castAs<CFGInitializer>();
590  SM, CallerCtx);
591  }
593  const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
595  SM, CallerCtx);
596  }
597  case CFGElement::DeleteDtor: {
598  const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
599  return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
600  }
602  case CFGElement::MemberDtor: {
603  const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
604  if (const Stmt *CallerBody = CallerInfo->getBody())
605  return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
606  return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
607  }
609  const CFGNewAllocator &Alloc = Source.castAs<CFGNewAllocator>();
610  return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerCtx);
611  }
613  // Temporary destructors are for temporaries. They die immediately at around
614  // the location of CXXBindTemporaryExpr. If they are lifetime-extended,
615  // they'd be dealt with via an AutomaticObjectDtor instead.
616  const auto &Dtor = Source.castAs<CFGTemporaryDtor>();
617  return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM,
618  CallerCtx);
619  }
622  llvm_unreachable("not yet implemented!");
625  llvm_unreachable("CFGElement kind should not be on callsite!");
626  }
627 
628  llvm_unreachable("Unknown CFGElement kind");
629 }
630 
633  const SourceManager &SM) {
634  return PathDiagnosticLocation(D->getLocStart(), SM, SingleLocK);
635 }
636 
639  const SourceManager &SM,
642  SM, SingleLocK);
643 }
644 
647  const SourceManager &SM,
649  if (const auto *CS = dyn_cast<CompoundStmt>(S))
650  return createEndBrace(CS, SM);
651  return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
652  SM, SingleLocK);
653 }
654 
657  const SourceManager &SM) {
658  return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
659 }
660 
663  const ConditionalOperator *CO,
664  const SourceManager &SM) {
665  return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
666 }
667 
670  const SourceManager &SM) {
671  return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
672 }
673 
676  const SourceManager &SM) {
677  SourceLocation L = CS->getLBracLoc();
678  return PathDiagnosticLocation(L, SM, SingleLocK);
679 }
680 
683  const SourceManager &SM) {
684  SourceLocation L = CS->getRBracLoc();
685  return PathDiagnosticLocation(L, SM, SingleLocK);
686 }
687 
690  const SourceManager &SM) {
691  // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
692  if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
693  if (!CS->body_empty()) {
694  SourceLocation Loc = (*CS->body_begin())->getLocStart();
695  return PathDiagnosticLocation(Loc, SM, SingleLocK);
696  }
697 
698  return PathDiagnosticLocation();
699 }
700 
703  const SourceManager &SM) {
704  SourceLocation L = LC->getDecl()->getBodyRBrace();
705  return PathDiagnosticLocation(L, SM, SingleLocK);
706 }
707 
710  const SourceManager &SMng) {
711  const Stmt* S = nullptr;
712  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
713  const CFGBlock *BSrc = BE->getSrc();
714  S = BSrc->getTerminatorCondition();
715  } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
716  S = SP->getStmt();
719  } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
720  return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
721  SMng);
722  } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
723  return PathDiagnosticLocation(PIE->getLocation(), SMng);
724  } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
725  return getLocationForCaller(CE->getCalleeContext(),
726  CE->getLocationContext(),
727  SMng);
728  } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
729  return getLocationForCaller(CEE->getCalleeContext(),
730  CEE->getLocationContext(),
731  SMng);
732  } else if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
733  CFGElement BlockFront = BE->getBlock()->front();
734  if (auto StmtElt = BlockFront.getAs<CFGStmt>()) {
735  return PathDiagnosticLocation(StmtElt->getStmt()->getLocStart(), SMng);
736  } else if (auto NewAllocElt = BlockFront.getAs<CFGNewAllocator>()) {
737  return PathDiagnosticLocation(
738  NewAllocElt->getAllocatorExpr()->getLocStart(), SMng);
739  }
740  llvm_unreachable("Unexpected CFG element at front of block");
741  } else {
742  llvm_unreachable("Unexpected ProgramPoint");
743  }
744 
745  return PathDiagnosticLocation(S, SMng, P.getLocationContext());
746 }
747 
748 static const LocationContext *
751  const LocationContext *ParentLC = LC->getParent();
752  assert(ParentLC && "We don't start analysis from autosynthesized code");
753  while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
754  LC = ParentLC;
755  ParentLC = LC->getParent();
756  assert(ParentLC && "We don't start analysis from autosynthesized code");
757  }
758  return LC;
759 }
760 
762  // We cannot place diagnostics on autosynthesized code.
763  // Put them onto the call site through which we jumped into autosynthesized
764  // code for the first time.
765  const LocationContext *LC = N->getLocationContext();
767  // It must be a stack frame because we only autosynthesize functions.
768  return cast<StackFrameContext>(findTopAutosynthesizedParentContext(LC))
769  ->getCallSite();
770  }
771  // Otherwise, see if the node's program point directly points to a statement.
772  ProgramPoint P = N->getLocation();
773  if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
774  return SP->getStmt();
775  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>())
776  return BE->getSrc()->getTerminator();
777  if (Optional<CallEnter> CE = P.getAs<CallEnter>())
778  return CE->getCallExpr();
779  if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>())
780  return CEE->getCalleeContext()->getCallSite();
782  return PIPP->getInitializer()->getInit();
784  return CEB->getReturnStmt();
785 
786  return nullptr;
787 }
788 
790  for (N = N->getFirstSucc(); N; N = N->getFirstSucc()) {
791  if (const Stmt *S = getStmt(N)) {
792  // Check if the statement is '?' or '&&'/'||'. These are "merges",
793  // not actual statement points.
794  switch (S->getStmtClass()) {
795  case Stmt::ChooseExprClass:
796  case Stmt::BinaryConditionalOperatorClass:
797  case Stmt::ConditionalOperatorClass:
798  continue;
799  case Stmt::BinaryOperatorClass: {
800  BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
801  if (Op == BO_LAnd || Op == BO_LOr)
802  continue;
803  break;
804  }
805  default:
806  break;
807  }
808  // We found the statement, so return it.
809  return S;
810  }
811  }
812 
813  return nullptr;
814 }
815 
818  const SourceManager &SM) {
819  assert(N && "Cannot create a location with a null node.");
820  const Stmt *S = getStmt(N);
821 
822  if (!S) {
823  // If this is an implicit call, return the implicit call point location.
825  return PathDiagnosticLocation(PIE->getLocation(), SM);
826  S = getNextStmt(N);
827  }
828 
829  if (S) {
830  ProgramPoint P = N->getLocation();
831  const LocationContext *LC = N->getLocationContext();
832 
833  // For member expressions, return the location of the '.' or '->'.
834  if (const auto *ME = dyn_cast<MemberExpr>(S))
836 
837  // For binary operators, return the location of the operator.
838  if (const auto *B = dyn_cast<BinaryOperator>(S))
840 
842  return PathDiagnosticLocation::createEnd(S, SM, LC);
843 
844  if (S->getLocStart().isValid())
845  return PathDiagnosticLocation(S, SM, LC);
847  }
848 
849  return createDeclEnd(N->getLocationContext(), SM);
850 }
851 
853  const PathDiagnosticLocation &PDL) {
854  FullSourceLoc L = PDL.asLocation();
855  return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
856 }
857 
859  PathDiagnosticLocation::genLocation(SourceLocation L,
860  LocationOrAnalysisDeclContext LAC) const {
861  assert(isValid());
862  // Note that we want a 'switch' here so that the compiler can warn us in
863  // case we add more cases.
864  switch (K) {
865  case SingleLocK:
866  case RangeK:
867  break;
868  case StmtK:
869  // Defensive checking.
870  if (!S)
871  break;
872  return FullSourceLoc(getValidSourceLocation(S, LAC),
873  const_cast<SourceManager&>(*SM));
874  case DeclK:
875  // Defensive checking.
876  if (!D)
877  break;
878  return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
879  }
880 
881  return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
882 }
883 
885  PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
886  assert(isValid());
887  // Note that we want a 'switch' here so that the compiler can warn us in
888  // case we add more cases.
889  switch (K) {
890  case SingleLocK:
891  return PathDiagnosticRange(SourceRange(Loc,Loc), true);
892  case RangeK:
893  break;
894  case StmtK: {
895  const Stmt *S = asStmt();
896  switch (S->getStmtClass()) {
897  default:
898  break;
899  case Stmt::DeclStmtClass: {
900  const auto *DS = cast<DeclStmt>(S);
901  if (DS->isSingleDecl()) {
902  // Should always be the case, but we'll be defensive.
903  return SourceRange(DS->getLocStart(),
904  DS->getSingleDecl()->getLocation());
905  }
906  break;
907  }
908  // FIXME: Provide better range information for different
909  // terminators.
910  case Stmt::IfStmtClass:
911  case Stmt::WhileStmtClass:
912  case Stmt::DoStmtClass:
913  case Stmt::ForStmtClass:
914  case Stmt::ChooseExprClass:
915  case Stmt::IndirectGotoStmtClass:
916  case Stmt::SwitchStmtClass:
917  case Stmt::BinaryConditionalOperatorClass:
918  case Stmt::ConditionalOperatorClass:
919  case Stmt::ObjCForCollectionStmtClass: {
921  return SourceRange(L, L);
922  }
923  }
924  SourceRange R = S->getSourceRange();
925  if (R.isValid())
926  return R;
927  break;
928  }
929  case DeclK:
930  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
931  return MD->getSourceRange();
932  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
933  if (Stmt *Body = FD->getBody())
934  return Body->getSourceRange();
935  }
936  else {
937  SourceLocation L = D->getLocation();
938  return PathDiagnosticRange(SourceRange(L, L), true);
939  }
940  }
941 
942  return SourceRange(Loc, Loc);
943 }
944 
946  if (K == StmtK) {
947  K = RangeK;
948  S = nullptr;
949  D = nullptr;
950  }
951  else if (K == DeclK) {
952  K = SingleLocK;
953  S = nullptr;
954  D = nullptr;
955  }
956 }
957 
958 //===----------------------------------------------------------------------===//
959 // Manipulation of PathDiagnosticCallPieces.
960 //===----------------------------------------------------------------------===//
961 
962 std::shared_ptr<PathDiagnosticCallPiece>
964  const SourceManager &SM) {
965  const Decl *caller = CE.getLocationContext()->getDecl();
967  CE.getLocationContext(),
968  SM);
969  return std::shared_ptr<PathDiagnosticCallPiece>(
970  new PathDiagnosticCallPiece(caller, pos));
971 }
972 
975  const Decl *caller) {
976  std::shared_ptr<PathDiagnosticCallPiece> C(
977  new PathDiagnosticCallPiece(path, caller));
978  path.clear();
979  auto *R = C.get();
980  path.push_front(std::move(C));
981  return R;
982 }
983 
985  const SourceManager &SM) {
986  const StackFrameContext *CalleeCtx = CE.getCalleeContext();
987  Callee = CalleeCtx->getDecl();
988 
989  callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
990  callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
991 
992  // Autosynthesized property accessors are special because we'd never
993  // pop back up to non-autosynthesized code until we leave them.
994  // This is not generally true for autosynthesized callees, which may call
995  // non-autosynthesized callbacks.
996  // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
997  // defaults to false.
998  if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
999  IsCalleeAnAutosynthesizedPropertyAccessor = (
1000  MD->isPropertyAccessor() &&
1002 }
1003 
1004 static void describeTemplateParameters(raw_ostream &Out,
1005  const ArrayRef<TemplateArgument> TAList,
1006  const LangOptions &LO,
1007  StringRef Prefix = StringRef(),
1008  StringRef Postfix = StringRef());
1009 
1010 static void describeTemplateParameter(raw_ostream &Out,
1011  const TemplateArgument &TArg,
1012  const LangOptions &LO) {
1013 
1014  if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
1015  describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
1016  } else {
1017  TArg.print(PrintingPolicy(LO), Out);
1018  }
1019 }
1020 
1021 static void describeTemplateParameters(raw_ostream &Out,
1022  const ArrayRef<TemplateArgument> TAList,
1023  const LangOptions &LO,
1024  StringRef Prefix, StringRef Postfix) {
1025  if (TAList.empty())
1026  return;
1027 
1028  Out << Prefix;
1029  for (int I = 0, Last = TAList.size() - 1; I != Last; ++I) {
1030  describeTemplateParameter(Out, TAList[I], LO);
1031  Out << ", ";
1032  }
1033  describeTemplateParameter(Out, TAList[TAList.size() - 1], LO);
1034  Out << Postfix;
1035 }
1036 
1037 static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
1038  StringRef Prefix = StringRef()) {
1039  if (!D->getIdentifier())
1040  return;
1041  Out << Prefix << '\'' << *D;
1042  if (const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
1043  describeTemplateParameters(Out, T->getTemplateArgs().asArray(),
1044  D->getASTContext().getLangOpts(), "<", ">");
1045 
1046  Out << '\'';
1047 }
1048 
1049 static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
1050  bool ExtendedDescription,
1051  StringRef Prefix = StringRef()) {
1052  if (!D)
1053  return false;
1054 
1055  if (isa<BlockDecl>(D)) {
1056  if (ExtendedDescription)
1057  Out << Prefix << "anonymous block";
1058  return ExtendedDescription;
1059  }
1060 
1061  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
1062  Out << Prefix;
1063  if (ExtendedDescription && !MD->isUserProvided()) {
1064  if (MD->isExplicitlyDefaulted())
1065  Out << "defaulted ";
1066  else
1067  Out << "implicit ";
1068  }
1069 
1070  if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
1071  if (CD->isDefaultConstructor())
1072  Out << "default ";
1073  else if (CD->isCopyConstructor())
1074  Out << "copy ";
1075  else if (CD->isMoveConstructor())
1076  Out << "move ";
1077 
1078  Out << "constructor";
1079  describeClass(Out, MD->getParent(), " for ");
1080  } else if (isa<CXXDestructorDecl>(MD)) {
1081  if (!MD->isUserProvided()) {
1082  Out << "destructor";
1083  describeClass(Out, MD->getParent(), " for ");
1084  } else {
1085  // Use ~Foo for explicitly-written destructors.
1086  Out << "'" << *MD << "'";
1087  }
1088  } else if (MD->isCopyAssignmentOperator()) {
1089  Out << "copy assignment operator";
1090  describeClass(Out, MD->getParent(), " for ");
1091  } else if (MD->isMoveAssignmentOperator()) {
1092  Out << "move assignment operator";
1093  describeClass(Out, MD->getParent(), " for ");
1094  } else {
1095  if (MD->getParent()->getIdentifier())
1096  Out << "'" << *MD->getParent() << "::" << *MD << "'";
1097  else
1098  Out << "'" << *MD << "'";
1099  }
1100 
1101  return true;
1102  }
1103 
1104  Out << Prefix << '\'' << cast<NamedDecl>(*D);
1105 
1106  // Adding template parameters.
1107  if (const auto FD = dyn_cast<FunctionDecl>(D))
1108  if (const TemplateArgumentList *TAList =
1109  FD->getTemplateSpecializationArgs())
1110  describeTemplateParameters(Out, TAList->asArray(),
1111  FD->getASTContext().getLangOpts(), "<", ">");
1112 
1113  Out << '\'';
1114  return true;
1115 }
1116 
1117 std::shared_ptr<PathDiagnosticEventPiece>
1119  // We do not produce call enters and call exits for autosynthesized property
1120  // accessors. We do generally produce them for other functions coming from
1121  // the body farm because they may call callbacks that bring us back into
1122  // visible code.
1123  if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
1124  return nullptr;
1125 
1126  SmallString<256> buf;
1127  llvm::raw_svector_ostream Out(buf);
1128 
1129  Out << "Calling ";
1130  describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
1131 
1132  assert(callEnter.asLocation().isValid());
1133  return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
1134 }
1135 
1136 std::shared_ptr<PathDiagnosticEventPiece>
1138  if (!callEnterWithin.asLocation().isValid())
1139  return nullptr;
1140  if (Callee->isImplicit() || !Callee->hasBody())
1141  return nullptr;
1142  if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
1143  if (MD->isDefaulted())
1144  return nullptr;
1145 
1146  SmallString<256> buf;
1147  llvm::raw_svector_ostream Out(buf);
1148 
1149  Out << "Entered call";
1150  describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
1151 
1152  return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
1153 }
1154 
1155 std::shared_ptr<PathDiagnosticEventPiece>
1157  // We do not produce call enters and call exits for autosynthesized property
1158  // accessors. We do generally produce them for other functions coming from
1159  // the body farm because they may call callbacks that bring us back into
1160  // visible code.
1161  if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
1162  return nullptr;
1163 
1164  SmallString<256> buf;
1165  llvm::raw_svector_ostream Out(buf);
1166 
1167  if (!CallStackMessage.empty()) {
1168  Out << CallStackMessage;
1169  } else {
1170  bool DidDescribe = describeCodeDecl(Out, Callee,
1171  /*ExtendedDescription=*/false,
1172  "Returning from ");
1173  if (!DidDescribe)
1174  Out << "Returning to caller";
1175  }
1176 
1177  assert(callReturn.asLocation().isValid());
1178  return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
1179 }
1180 
1181 static void compute_path_size(const PathPieces &pieces, unsigned &size) {
1182  for (const auto &I : pieces) {
1183  const PathDiagnosticPiece *piece = I.get();
1184  if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
1185  compute_path_size(cp->path, size);
1186  else
1187  ++size;
1188  }
1189 }
1190 
1192  unsigned size = 0;
1193  compute_path_size(path, size);
1194  return size;
1195 }
1196 
1197 //===----------------------------------------------------------------------===//
1198 // FoldingSet profiling methods.
1199 //===----------------------------------------------------------------------===//
1200 
1201 void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
1202  ID.AddInteger(Range.getBegin().getRawEncoding());
1203  ID.AddInteger(Range.getEnd().getRawEncoding());
1204  ID.AddInteger(Loc.getRawEncoding());
1205 }
1206 
1207 void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1208  ID.AddInteger((unsigned) getKind());
1209  ID.AddString(str);
1210  // FIXME: Add profiling support for code hints.
1211  ID.AddInteger((unsigned) getDisplayHint());
1212  ArrayRef<SourceRange> Ranges = getRanges();
1213  for (const auto &I : Ranges) {
1214  ID.AddInteger(I.getBegin().getRawEncoding());
1215  ID.AddInteger(I.getEnd().getRawEncoding());
1216  }
1217 }
1218 
1219 void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1221  for (const auto &I : path)
1222  ID.Add(*I);
1223 }
1224 
1225 void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1227  ID.Add(Pos);
1228 }
1229 
1230 void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1232  for (const auto &I : *this)
1233  ID.Add(I);
1234 }
1235 
1236 void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1238  for (const auto &I : subPieces)
1239  ID.Add(*I);
1240 }
1241 
1242 void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
1244 }
1245 
1246 void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
1247  ID.Add(getLocation());
1248  ID.AddString(BugType);
1249  ID.AddString(VerboseDesc);
1250  ID.AddString(Category);
1251 }
1252 
1253 void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1254  Profile(ID);
1255  for (const auto &I : path)
1256  ID.Add(*I);
1257  for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1258  ID.AddString(*I);
1259 }
1260 
1262 
1264  if (!N)
1265  return getMessageForSymbolNotFound();
1266 
1267  ProgramPoint P = N->getLocation();
1268  CallExitEnd CExit = P.castAs<CallExitEnd>();
1269 
1270  // FIXME: Use CallEvent to abstract this over all calls.
1271  const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
1272  const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
1273  if (!CE)
1274  return {};
1275 
1276  // Check if one of the parameters are set to the interesting symbol.
1277  unsigned ArgIndex = 0;
1278  for (CallExpr::const_arg_iterator I = CE->arg_begin(),
1279  E = CE->arg_end(); I != E; ++I, ++ArgIndex){
1280  SVal SV = N->getSVal(*I);
1281 
1282  // Check if the variable corresponding to the symbol is passed by value.
1283  SymbolRef AS = SV.getAsLocSymbol();
1284  if (AS == Sym) {
1285  return getMessageForArg(*I, ArgIndex);
1286  }
1287 
1288  // Check if the parameter is a pointer to the symbol.
1290  // Do not attempt to dereference void*.
1291  if ((*I)->getType()->isVoidPointerType())
1292  continue;
1293  SVal PSV = N->getState()->getSVal(Reg->getRegion());
1294  SymbolRef AS = PSV.getAsLocSymbol();
1295  if (AS == Sym) {
1296  return getMessageForArg(*I, ArgIndex);
1297  }
1298  }
1299  }
1300 
1301  // Check if we are returning the interesting symbol.
1302  SVal SV = N->getSVal(CE);
1303  SymbolRef RetSym = SV.getAsLocSymbol();
1304  if (RetSym == Sym) {
1305  return getMessageForReturn(CE);
1306  }
1307 
1308  return getMessageForSymbolNotFound();
1309 }
1310 
1312  unsigned ArgIndex) {
1313  // Printed parameters start at 1, not 0.
1314  ++ArgIndex;
1315 
1316  SmallString<200> buf;
1317  llvm::raw_svector_ostream os(buf);
1318 
1319  os << Msg << " via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1320  << " parameter";
1321 
1322  return os.str();
1323 }
1324 
1325 LLVM_DUMP_METHOD void PathPieces::dump() const {
1326  unsigned index = 0;
1327  for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
1328  llvm::errs() << "[" << index++ << "] ";
1329  (*I)->dump();
1330  llvm::errs() << "\n";
1331  }
1332 }
1333 
1334 LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const {
1335  llvm::errs() << "CALL\n--------------\n";
1336 
1337  if (const Stmt *SLoc = getLocation().getStmtOrNull())
1338  SLoc->dump();
1339  else if (const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee()))
1340  llvm::errs() << *ND << "\n";
1341  else
1342  getLocation().dump();
1343 }
1344 
1345 LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const {
1346  llvm::errs() << "EVENT\n--------------\n";
1347  llvm::errs() << getString() << "\n";
1348  llvm::errs() << " ---- at ----\n";
1349  getLocation().dump();
1350 }
1351 
1352 LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const {
1353  llvm::errs() << "CONTROL\n--------------\n";
1354  getStartLocation().dump();
1355  llvm::errs() << " ---- to ----\n";
1356  getEndLocation().dump();
1357 }
1358 
1359 LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
1360  llvm::errs() << "MACRO\n--------------\n";
1361  // FIXME: Print which macro is being invoked.
1362 }
1363 
1364 LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const {
1365  llvm::errs() << "NOTE\n--------------\n";
1366  llvm::errs() << getString() << "\n";
1367  llvm::errs() << " ---- at ----\n";
1368  getLocation().dump();
1369 }
1370 
1371 LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const {
1372  if (!isValid()) {
1373  llvm::errs() << "<INVALID>\n";
1374  return;
1375  }
1376 
1377  switch (K) {
1378  case RangeK:
1379  // FIXME: actually print the range.
1380  llvm::errs() << "<range>\n";
1381  break;
1382  case SingleLocK:
1383  asLocation().dump();
1384  llvm::errs() << "\n";
1385  break;
1386  case StmtK:
1387  if (S)
1388  S->dump();
1389  else
1390  llvm::errs() << "<NULL STMT>\n";
1391  break;
1392  case DeclK:
1393  if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
1394  llvm::errs() << *ND << "\n";
1395  else if (isa<BlockDecl>(D))
1396  // FIXME: Make this nicer.
1397  llvm::errs() << "<block>\n";
1398  else if (D)
1399  llvm::errs() << "<unknown decl>\n";
1400  else
1401  llvm::errs() << "<NULL DECL>\n";
1402  break;
1403  }
1404 }
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:2433
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:600
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:553
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:3339
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:2022
StringRef getVerboseDescription() const
static const LocationContext * findTopAutosynthesizedParentContext(const LocationContext *LC)
int Category
Definition: Format.cpp:1601
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:638
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:3065
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:459
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:3349
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:658
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:5350
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 FunctionProtoType * T
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:1468
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:3103
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:570
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:610
void FlushDiagnostics(FilesMade *FilesMade)
BinaryOperator::Opcode getOpcode(const SymExpr *SE)
const StackFrameContext * getCalleeContext() const
Definition: ProgramPoint.h:665
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:13462
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
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.