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/Expr.h"
20 #include "clang/AST/ExprCXX.h"
22 #include "clang/AST/ParentMap.h"
23 #include "clang/AST/Stmt.h"
24 #include "clang/AST/Type.h"
26 #include "clang/Analysis/CFG.h"
29 #include "clang/Basic/LLVM.h"
35 #include "llvm/ADT/ArrayRef.h"
36 #include "llvm/ADT/FoldingSet.h"
37 #include "llvm/ADT/None.h"
38 #include "llvm/ADT/Optional.h"
39 #include "llvm/ADT/STLExtras.h"
40 #include "llvm/ADT/SmallString.h"
41 #include "llvm/ADT/SmallVector.h"
42 #include "llvm/ADT/StringExtras.h"
43 #include "llvm/ADT/StringRef.h"
44 #include "llvm/Support/Casting.h"
45 #include "llvm/Support/ErrorHandling.h"
46 #include "llvm/Support/raw_ostream.h"
47 #include <cassert>
48 #include <cstring>
49 #include <memory>
50 #include <utility>
51 #include <vector>
52 
53 using namespace clang;
54 using namespace ento;
55 
57  for (const auto &P : subPieces) {
58  if (isa<PathDiagnosticEventPiece>(*P))
59  return true;
60  if (const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(P.get()))
61  if (MP->containsEvent())
62  return true;
63  }
64  return false;
65 }
66 
67 static StringRef StripTrailingDots(StringRef s) {
68  for (StringRef::size_type i = s.size(); i != 0; --i)
69  if (s[i - 1] != '.')
70  return s.substr(0, i);
71  return {};
72 }
73 
75  Kind k, DisplayHint hint)
76  : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
77 
79  : kind(k), Hint(hint) {}
80 
82 
84 
86 
88 
90 
92 
93 void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
94  bool ShouldFlattenMacros) const {
95  for (auto &Piece : *this) {
96  switch (Piece->getKind()) {
98  auto &Call = cast<PathDiagnosticCallPiece>(*Piece);
99  if (auto CallEnter = Call.getCallEnterEvent())
100  Current.push_back(std::move(CallEnter));
101  Call.path.flattenTo(Primary, Primary, ShouldFlattenMacros);
102  if (auto callExit = Call.getCallExitEvent())
103  Current.push_back(std::move(callExit));
104  break;
105  }
107  auto &Macro = cast<PathDiagnosticMacroPiece>(*Piece);
108  if (ShouldFlattenMacros) {
109  Macro.subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
110  } else {
111  Current.push_back(Piece);
112  PathPieces NewPath;
113  Macro.subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
114  // FIXME: This probably shouldn't mutate the original path piece.
115  Macro.subPieces = NewPath;
116  }
117  break;
118  }
122  Current.push_back(Piece);
123  break;
124  }
125  }
126 }
127 
129 
131  StringRef CheckName, const Decl *declWithIssue, StringRef bugtype,
132  StringRef verboseDesc, StringRef shortDesc, StringRef category,
133  PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique,
134  std::unique_ptr<FilesToLineNumsMap> ExecutedLines)
135  : CheckName(CheckName), DeclWithIssue(declWithIssue),
136  BugType(StripTrailingDots(bugtype)),
137  VerboseDesc(StripTrailingDots(verboseDesc)),
138  ShortDesc(StripTrailingDots(shortDesc)),
139  Category(StripTrailingDots(category)), UniqueingLoc(LocationToUnique),
140  UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)),
141  path(pathImpl) {}
142 
145  const SourceManager &SMgr) {
146  SourceLocation CallLoc = CP->callEnter.asLocation();
147 
148  // If the call is within a macro, don't do anything (for now).
149  if (CallLoc.isMacroID())
150  return nullptr;
151 
152  assert(AnalysisManager::isInCodeFile(CallLoc, SMgr) &&
153  "The call piece should not be in a header file.");
154 
155  // Check if CP represents a path through a function outside of the main file.
157  return CP;
158 
159  const PathPieces &Path = CP->path;
160  if (Path.empty())
161  return nullptr;
162 
163  // Check if the last piece in the callee path is a call to a function outside
164  // of the main file.
165  if (auto *CPInner = dyn_cast<PathDiagnosticCallPiece>(Path.back().get()))
166  return getFirstStackedCallToHeaderFile(CPInner, SMgr);
167 
168  // Otherwise, the last piece is in the main file.
169  return nullptr;
170 }
171 
173  if (path.empty())
174  return;
175 
176  PathDiagnosticPiece *LastP = path.back().get();
177  assert(LastP);
178  const SourceManager &SMgr = LastP->getLocation().getManager();
179 
180  // We only need to check if the report ends inside headers, if the last piece
181  // is a call piece.
182  if (auto *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
183  CP = getFirstStackedCallToHeaderFile(CP, SMgr);
184  if (CP) {
185  // Mark the piece.
186  CP->setAsLastInMainSourceFile();
187 
188  // Update the path diagnostic message.
189  const auto *ND = dyn_cast<NamedDecl>(CP->getCallee());
190  if (ND) {
191  SmallString<200> buf;
192  llvm::raw_svector_ostream os(buf);
193  os << " (within a call to '" << ND->getDeclName() << "')";
194  appendToDesc(os.str());
195  }
196 
197  // Reset the report containing declaration and location.
198  DeclWithIssue = CP->getCaller();
199  Loc = CP->getLocation();
200 
201  return;
202  }
203  }
204 }
205 
206 void PathDiagnosticConsumer::anchor() {}
207 
209  // Delete the contents of the FoldingSet if it isn't empty already.
210  for (auto &Diag : Diags)
211  delete &Diag;
212 }
213 
215  std::unique_ptr<PathDiagnostic> D) {
216  if (!D || D->path.empty())
217  return;
218 
219  // We need to flatten the locations (convert Stmt* to locations) because
220  // the referenced statements may be freed by the time the diagnostics
221  // are emitted.
222  D->flattenLocations();
223 
224  // If the PathDiagnosticConsumer does not support diagnostics that
225  // cross file boundaries, prune out such diagnostics now.
226  if (!supportsCrossFileDiagnostics()) {
227  // Verify that the entire path is from the same FileID.
228  FileID FID;
229  const SourceManager &SMgr = D->path.front()->getLocation().getManager();
231  WorkList.push_back(&D->path);
232  SmallString<128> buf;
233  llvm::raw_svector_ostream warning(buf);
234  warning << "warning: Path diagnostic report is not generated. Current "
235  << "output format does not support diagnostics that cross file "
236  << "boundaries. Refer to --analyzer-output for valid output "
237  << "formats\n";
238 
239  while (!WorkList.empty()) {
240  const PathPieces &path = *WorkList.pop_back_val();
241 
242  for (const auto &I : path) {
243  const PathDiagnosticPiece *piece = I.get();
245 
246  if (FID.isInvalid()) {
247  FID = SMgr.getFileID(L);
248  } else if (SMgr.getFileID(L) != FID) {
249  llvm::errs() << warning.str();
250  return;
251  }
252 
253  // Check the source ranges.
254  ArrayRef<SourceRange> Ranges = piece->getRanges();
255  for (const auto &I : Ranges) {
256  SourceLocation L = SMgr.getExpansionLoc(I.getBegin());
257  if (!L.isFileID() || SMgr.getFileID(L) != FID) {
258  llvm::errs() << warning.str();
259  return;
260  }
261  L = SMgr.getExpansionLoc(I.getEnd());
262  if (!L.isFileID() || SMgr.getFileID(L) != FID) {
263  llvm::errs() << warning.str();
264  return;
265  }
266  }
267 
268  if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece))
269  WorkList.push_back(&call->path);
270  else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece))
271  WorkList.push_back(&macro->subPieces);
272  }
273  }
274 
275  if (FID.isInvalid())
276  return; // FIXME: Emit a warning?
277  }
278 
279  // Profile the node to see if we already have something matching it
280  llvm::FoldingSetNodeID profile;
281  D->Profile(profile);
282  void *InsertPos = nullptr;
283 
284  if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
285  // Keep the PathDiagnostic with the shorter path.
286  // Note, the enclosing routine is called in deterministic order, so the
287  // results will be consistent between runs (no reason to break ties if the
288  // size is the same).
289  const unsigned orig_size = orig->full_size();
290  const unsigned new_size = D->full_size();
291  if (orig_size <= new_size)
292  return;
293 
294  assert(orig != D.get());
295  Diags.RemoveNode(orig);
296  delete orig;
297  }
298 
299  Diags.InsertNode(D.release());
300 }
301 
302 static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y);
303 
304 static Optional<bool>
309  if (XSL != YSL)
310  return XSL.isBeforeInTranslationUnitThan(YSL);
313  if (XEL != YEL)
314  return XEL.isBeforeInTranslationUnitThan(YEL);
315  return None;
316 }
317 
319  const PathDiagnosticMacroPiece &Y) {
320  return comparePath(X.subPieces, Y.subPieces);
321 }
322 
324  const PathDiagnosticCallPiece &Y) {
325  FullSourceLoc X_CEL = X.callEnter.asLocation();
326  FullSourceLoc Y_CEL = Y.callEnter.asLocation();
327  if (X_CEL != Y_CEL)
328  return X_CEL.isBeforeInTranslationUnitThan(Y_CEL);
331  if (X_CEWL != Y_CEWL)
332  return X_CEWL.isBeforeInTranslationUnitThan(Y_CEWL);
333  FullSourceLoc X_CRL = X.callReturn.asLocation();
334  FullSourceLoc Y_CRL = Y.callReturn.asLocation();
335  if (X_CRL != Y_CRL)
336  return X_CRL.isBeforeInTranslationUnitThan(Y_CRL);
337  return comparePath(X.path, Y.path);
338 }
339 
341  const PathDiagnosticPiece &Y) {
342  if (X.getKind() != Y.getKind())
343  return X.getKind() < Y.getKind();
344 
347  if (XL != YL)
348  return XL.isBeforeInTranslationUnitThan(YL);
349 
350  if (X.getString() != Y.getString())
351  return X.getString() < Y.getString();
352 
353  if (X.getRanges().size() != Y.getRanges().size())
354  return X.getRanges().size() < Y.getRanges().size();
355 
356  const SourceManager &SM = XL.getManager();
357 
358  for (unsigned i = 0, n = X.getRanges().size(); i < n; ++i) {
359  SourceRange XR = X.getRanges()[i];
360  SourceRange YR = Y.getRanges()[i];
361  if (XR != YR) {
362  if (XR.getBegin() != YR.getBegin())
363  return SM.isBeforeInTranslationUnit(XR.getBegin(), YR.getBegin());
364  return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd());
365  }
366  }
367 
368  switch (X.getKind()) {
370  return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X),
371  cast<PathDiagnosticControlFlowPiece>(Y));
374  return None;
376  return compareMacro(cast<PathDiagnosticMacroPiece>(X),
377  cast<PathDiagnosticMacroPiece>(Y));
379  return compareCall(cast<PathDiagnosticCallPiece>(X),
380  cast<PathDiagnosticCallPiece>(Y));
381  }
382  llvm_unreachable("all cases handled");
383 }
384 
385 static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) {
386  if (X.size() != Y.size())
387  return X.size() < Y.size();
388 
389  PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
390  PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
391 
392  for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) {
393  Optional<bool> b = comparePiece(**X_I, **Y_I);
394  if (b.hasValue())
395  return b.getValue();
396  }
397 
398  return None;
399 }
400 
402  std::pair<FileID, unsigned> XOffs = XL.getDecomposedLoc();
403  std::pair<FileID, unsigned> YOffs = YL.getDecomposedLoc();
404  const SourceManager &SM = XL.getManager();
405  std::pair<bool, bool> InSameTU = SM.isInTheSameTranslationUnit(XOffs, YOffs);
406  if (InSameTU.first)
407  return XL.isBeforeInTranslationUnitThan(YL);
408  const FileEntry *XFE = SM.getFileEntryForID(XL.getFileID());
409  const FileEntry *YFE = SM.getFileEntryForID(YL.getFileID());
410  if (!XFE || !YFE)
411  return XFE && !YFE;
412  return XFE->getName() < YFE->getName();
413 }
414 
415 static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
418  if (XL != YL)
419  return compareCrossTUSourceLocs(XL, YL);
420  if (X.getBugType() != Y.getBugType())
421  return X.getBugType() < Y.getBugType();
422  if (X.getCategory() != Y.getCategory())
423  return X.getCategory() < Y.getCategory();
427  return X.getShortDescription() < Y.getShortDescription();
428  if (X.getDeclWithIssue() != Y.getDeclWithIssue()) {
429  const Decl *XD = X.getDeclWithIssue();
430  if (!XD)
431  return true;
432  const Decl *YD = Y.getDeclWithIssue();
433  if (!YD)
434  return false;
435  SourceLocation XDL = XD->getLocation();
436  SourceLocation YDL = YD->getLocation();
437  if (XDL != YDL) {
438  const SourceManager &SM = XL.getManager();
439  return compareCrossTUSourceLocs(FullSourceLoc(XDL, SM),
440  FullSourceLoc(YDL, SM));
441  }
442  }
445  if (XE - XI != YE - YI)
446  return (XE - XI) < (YE - YI);
447  for ( ; XI != XE ; ++XI, ++YI) {
448  if (*XI != *YI)
449  return (*XI) < (*YI);
450  }
452  assert(b.hasValue());
453  return b.getValue();
454 }
455 
458  if (flushed)
459  return;
460 
461  flushed = true;
462 
463  std::vector<const PathDiagnostic *> BatchDiags;
464  for (const auto &D : Diags)
465  BatchDiags.push_back(&D);
466 
467  // Sort the diagnostics so that they are always emitted in a deterministic
468  // order.
469  int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
470  [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
471  assert(*X != *Y && "PathDiagnostics not uniqued!");
472  if (compare(**X, **Y))
473  return -1;
474  assert(compare(**Y, **X) && "Not a total order!");
475  return 1;
476  };
477  array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
478 
479  FlushDiagnosticsImpl(BatchDiags, Files);
480 
481  // Delete the flushed diagnostics.
482  for (const auto D : BatchDiags)
483  delete D;
484 
485  // Clear out the FoldingSet.
486  Diags.clear();
487 }
488 
490  for (PDFileEntry &Entry : Set)
491  Entry.~PDFileEntry();
492 }
493 
495  StringRef ConsumerName,
496  StringRef FileName) {
497  llvm::FoldingSetNodeID NodeID;
498  NodeID.Add(PD);
499  void *InsertPos;
500  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
501  if (!Entry) {
502  Entry = Alloc.Allocate<PDFileEntry>();
503  Entry = new (Entry) PDFileEntry(NodeID);
504  Set.InsertNode(Entry, InsertPos);
505  }
506 
507  // Allocate persistent storage for the file name.
508  char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
509  memcpy(FileName_cstr, FileName.data(), FileName.size());
510 
511  Entry->files.push_back(std::make_pair(ConsumerName,
512  StringRef(FileName_cstr,
513  FileName.size())));
514 }
515 
518  llvm::FoldingSetNodeID NodeID;
519  NodeID.Add(PD);
520  void *InsertPos;
521  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
522  if (!Entry)
523  return nullptr;
524  return &Entry->files;
525 }
526 
527 //===----------------------------------------------------------------------===//
528 // PathDiagnosticLocation methods.
529 //===----------------------------------------------------------------------===//
530 
533  bool UseEnd = false) {
534  SourceLocation L = UseEnd ? S->getLocEnd() : S->getLocStart();
535  assert(!LAC.isNull() && "A valid LocationContext or AnalysisDeclContext should "
536  "be passed to PathDiagnosticLocation upon creation.");
537 
538  // S might be a temporary statement that does not have a location in the
539  // source code, so find an enclosing statement and use its location.
540  if (!L.isValid()) {
541  AnalysisDeclContext *ADC;
542  if (LAC.is<const LocationContext*>())
543  ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext();
544  else
545  ADC = LAC.get<AnalysisDeclContext*>();
546 
547  ParentMap &PM = ADC->getParentMap();
548 
549  const Stmt *Parent = S;
550  do {
551  Parent = PM.getParent(Parent);
552 
553  // In rare cases, we have implicit top-level expressions,
554  // such as arguments for implicit member initializers.
555  // In this case, fall back to the start of the body (even if we were
556  // asked for the statement end location).
557  if (!Parent) {
558  const Stmt *Body = ADC->getBody();
559  if (Body)
560  L = Body->getLocStart();
561  else
562  L = ADC->getDecl()->getLocEnd();
563  break;
564  }
565 
566  L = UseEnd ? Parent->getLocEnd() : Parent->getLocStart();
567  } while (!L.isValid());
568  }
569 
570  return L;
571 }
572 
575  const LocationContext *CallerCtx,
576  const SourceManager &SM) {
577  const CFGBlock &Block = *SFC->getCallSiteBlock();
578  CFGElement Source = Block[SFC->getIndex()];
579 
580  switch (Source.getKind()) {
584  return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
585  SM, CallerCtx);
587  const CFGInitializer &Init = Source.castAs<CFGInitializer>();
589  SM, CallerCtx);
590  }
592  const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
594  SM, CallerCtx);
595  }
596  case CFGElement::DeleteDtor: {
597  const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
598  return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
599  }
601  case CFGElement::MemberDtor: {
602  const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
603  if (const Stmt *CallerBody = CallerInfo->getBody())
604  return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
605  return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
606  }
608  const CFGNewAllocator &Alloc = Source.castAs<CFGNewAllocator>();
609  return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerCtx);
610  }
612  // Temporary destructors are for temporaries. They die immediately at around
613  // the location of CXXBindTemporaryExpr. If they are lifetime-extended,
614  // they'd be dealt with via an AutomaticObjectDtor instead.
615  const auto &Dtor = Source.castAs<CFGTemporaryDtor>();
616  return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM,
617  CallerCtx);
618  }
621  llvm_unreachable("not yet implemented!");
624  llvm_unreachable("CFGElement kind should not be on callsite!");
625  }
626 
627  llvm_unreachable("Unknown CFGElement kind");
628 }
629 
632  const SourceManager &SM) {
633  return PathDiagnosticLocation(D->getLocStart(), SM, SingleLocK);
634 }
635 
638  const SourceManager &SM,
641  SM, SingleLocK);
642 }
643 
646  const SourceManager &SM,
648  if (const auto *CS = dyn_cast<CompoundStmt>(S))
649  return createEndBrace(CS, SM);
650  return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
651  SM, SingleLocK);
652 }
653 
656  const SourceManager &SM) {
657  return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
658 }
659 
662  const ConditionalOperator *CO,
663  const SourceManager &SM) {
664  return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
665 }
666 
669  const SourceManager &SM) {
670  return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
671 }
672 
675  const SourceManager &SM) {
676  SourceLocation L = CS->getLBracLoc();
677  return PathDiagnosticLocation(L, SM, SingleLocK);
678 }
679 
682  const SourceManager &SM) {
683  SourceLocation L = CS->getRBracLoc();
684  return PathDiagnosticLocation(L, SM, SingleLocK);
685 }
686 
689  const SourceManager &SM) {
690  // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
691  if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
692  if (!CS->body_empty()) {
693  SourceLocation Loc = (*CS->body_begin())->getLocStart();
694  return PathDiagnosticLocation(Loc, SM, SingleLocK);
695  }
696 
697  return PathDiagnosticLocation();
698 }
699 
702  const SourceManager &SM) {
703  SourceLocation L = LC->getDecl()->getBodyRBrace();
704  return PathDiagnosticLocation(L, SM, SingleLocK);
705 }
706 
709  const SourceManager &SMng) {
710  const Stmt* S = nullptr;
711  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
712  const CFGBlock *BSrc = BE->getSrc();
713  S = BSrc->getTerminatorCondition();
714  } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
715  S = SP->getStmt();
718  } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
719  return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
720  SMng);
721  } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
722  return PathDiagnosticLocation(PIE->getLocation(), SMng);
723  } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
724  return getLocationForCaller(CE->getCalleeContext(),
725  CE->getLocationContext(),
726  SMng);
727  } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
728  return getLocationForCaller(CEE->getCalleeContext(),
729  CEE->getLocationContext(),
730  SMng);
731  } else if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
732  CFGElement BlockFront = BE->getBlock()->front();
733  if (auto StmtElt = BlockFront.getAs<CFGStmt>()) {
734  return PathDiagnosticLocation(StmtElt->getStmt()->getLocStart(), SMng);
735  } else if (auto NewAllocElt = BlockFront.getAs<CFGNewAllocator>()) {
736  return PathDiagnosticLocation(
737  NewAllocElt->getAllocatorExpr()->getLocStart(), SMng);
738  }
739  llvm_unreachable("Unexpected CFG element at front of block");
740  } else {
741  llvm_unreachable("Unexpected ProgramPoint");
742  }
743 
744  return PathDiagnosticLocation(S, SMng, P.getLocationContext());
745 }
746 
747 static const LocationContext *
750  const LocationContext *ParentLC = LC->getParent();
751  assert(ParentLC && "We don't start analysis from autosynthesized code");
752  while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
753  LC = ParentLC;
754  ParentLC = LC->getParent();
755  assert(ParentLC && "We don't start analysis from autosynthesized code");
756  }
757  return LC;
758 }
759 
761  // We cannot place diagnostics on autosynthesized code.
762  // Put them onto the call site through which we jumped into autosynthesized
763  // code for the first time.
764  const LocationContext *LC = N->getLocationContext();
766  // It must be a stack frame because we only autosynthesize functions.
767  return cast<StackFrameContext>(findTopAutosynthesizedParentContext(LC))
768  ->getCallSite();
769  }
770  // Otherwise, see if the node's program point directly points to a statement.
771  ProgramPoint P = N->getLocation();
772  if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
773  return SP->getStmt();
774  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>())
775  return BE->getSrc()->getTerminator();
776  if (Optional<CallEnter> CE = P.getAs<CallEnter>())
777  return CE->getCallExpr();
778  if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>())
779  return CEE->getCalleeContext()->getCallSite();
781  return PIPP->getInitializer()->getInit();
783  return CEB->getReturnStmt();
784 
785  return nullptr;
786 }
787 
789  for (N = N->getFirstSucc(); N; N = N->getFirstSucc()) {
790  if (const Stmt *S = getStmt(N)) {
791  // Check if the statement is '?' or '&&'/'||'. These are "merges",
792  // not actual statement points.
793  switch (S->getStmtClass()) {
794  case Stmt::ChooseExprClass:
795  case Stmt::BinaryConditionalOperatorClass:
796  case Stmt::ConditionalOperatorClass:
797  continue;
798  case Stmt::BinaryOperatorClass: {
799  BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
800  if (Op == BO_LAnd || Op == BO_LOr)
801  continue;
802  break;
803  }
804  default:
805  break;
806  }
807  // We found the statement, so return it.
808  return S;
809  }
810  }
811 
812  return nullptr;
813 }
814 
817  const SourceManager &SM) {
818  assert(N && "Cannot create a location with a null node.");
819  const Stmt *S = getStmt(N);
820 
821  if (!S) {
822  // If this is an implicit call, return the implicit call point location.
824  return PathDiagnosticLocation(PIE->getLocation(), SM);
825  S = getNextStmt(N);
826  }
827 
828  if (S) {
829  ProgramPoint P = N->getLocation();
830  const LocationContext *LC = N->getLocationContext();
831 
832  // For member expressions, return the location of the '.' or '->'.
833  if (const auto *ME = dyn_cast<MemberExpr>(S))
835 
836  // For binary operators, return the location of the operator.
837  if (const auto *B = dyn_cast<BinaryOperator>(S))
839 
841  return PathDiagnosticLocation::createEnd(S, SM, LC);
842 
843  if (S->getLocStart().isValid())
844  return PathDiagnosticLocation(S, SM, LC);
846  }
847 
848  return createDeclEnd(N->getLocationContext(), SM);
849 }
850 
852  const PathDiagnosticLocation &PDL) {
853  FullSourceLoc L = PDL.asLocation();
854  return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
855 }
856 
858  PathDiagnosticLocation::genLocation(SourceLocation L,
859  LocationOrAnalysisDeclContext LAC) const {
860  assert(isValid());
861  // Note that we want a 'switch' here so that the compiler can warn us in
862  // case we add more cases.
863  switch (K) {
864  case SingleLocK:
865  case RangeK:
866  break;
867  case StmtK:
868  // Defensive checking.
869  if (!S)
870  break;
871  return FullSourceLoc(getValidSourceLocation(S, LAC),
872  const_cast<SourceManager&>(*SM));
873  case DeclK:
874  // Defensive checking.
875  if (!D)
876  break;
877  return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
878  }
879 
880  return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
881 }
882 
884  PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
885  assert(isValid());
886  // Note that we want a 'switch' here so that the compiler can warn us in
887  // case we add more cases.
888  switch (K) {
889  case SingleLocK:
890  return PathDiagnosticRange(SourceRange(Loc,Loc), true);
891  case RangeK:
892  break;
893  case StmtK: {
894  const Stmt *S = asStmt();
895  switch (S->getStmtClass()) {
896  default:
897  break;
898  case Stmt::DeclStmtClass: {
899  const auto *DS = cast<DeclStmt>(S);
900  if (DS->isSingleDecl()) {
901  // Should always be the case, but we'll be defensive.
902  return SourceRange(DS->getLocStart(),
903  DS->getSingleDecl()->getLocation());
904  }
905  break;
906  }
907  // FIXME: Provide better range information for different
908  // terminators.
909  case Stmt::IfStmtClass:
910  case Stmt::WhileStmtClass:
911  case Stmt::DoStmtClass:
912  case Stmt::ForStmtClass:
913  case Stmt::ChooseExprClass:
914  case Stmt::IndirectGotoStmtClass:
915  case Stmt::SwitchStmtClass:
916  case Stmt::BinaryConditionalOperatorClass:
917  case Stmt::ConditionalOperatorClass:
918  case Stmt::ObjCForCollectionStmtClass: {
920  return SourceRange(L, L);
921  }
922  }
923  SourceRange R = S->getSourceRange();
924  if (R.isValid())
925  return R;
926  break;
927  }
928  case DeclK:
929  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
930  return MD->getSourceRange();
931  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
932  if (Stmt *Body = FD->getBody())
933  return Body->getSourceRange();
934  }
935  else {
936  SourceLocation L = D->getLocation();
937  return PathDiagnosticRange(SourceRange(L, L), true);
938  }
939  }
940 
941  return SourceRange(Loc, Loc);
942 }
943 
945  if (K == StmtK) {
946  K = RangeK;
947  S = nullptr;
948  D = nullptr;
949  }
950  else if (K == DeclK) {
951  K = SingleLocK;
952  S = nullptr;
953  D = nullptr;
954  }
955 }
956 
957 //===----------------------------------------------------------------------===//
958 // Manipulation of PathDiagnosticCallPieces.
959 //===----------------------------------------------------------------------===//
960 
961 std::shared_ptr<PathDiagnosticCallPiece>
963  const SourceManager &SM) {
964  const Decl *caller = CE.getLocationContext()->getDecl();
966  CE.getLocationContext(),
967  SM);
968  return std::shared_ptr<PathDiagnosticCallPiece>(
969  new PathDiagnosticCallPiece(caller, pos));
970 }
971 
974  const Decl *caller) {
975  std::shared_ptr<PathDiagnosticCallPiece> C(
976  new PathDiagnosticCallPiece(path, caller));
977  path.clear();
978  auto *R = C.get();
979  path.push_front(std::move(C));
980  return R;
981 }
982 
984  const SourceManager &SM) {
985  const StackFrameContext *CalleeCtx = CE.getCalleeContext();
986  Callee = CalleeCtx->getDecl();
987 
988  callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
989  callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
990 
991  // Autosynthesized property accessors are special because we'd never
992  // pop back up to non-autosynthesized code until we leave them.
993  // This is not generally true for autosynthesized callees, which may call
994  // non-autosynthesized callbacks.
995  // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
996  // defaults to false.
997  if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
998  IsCalleeAnAutosynthesizedPropertyAccessor = (
999  MD->isPropertyAccessor() &&
1001 }
1002 
1003 static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
1004  StringRef Prefix = StringRef()) {
1005  if (!D->getIdentifier())
1006  return;
1007  Out << Prefix << '\'' << *D << '\'';
1008 }
1009 
1010 static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
1011  bool ExtendedDescription,
1012  StringRef Prefix = StringRef()) {
1013  if (!D)
1014  return false;
1015 
1016  if (isa<BlockDecl>(D)) {
1017  if (ExtendedDescription)
1018  Out << Prefix << "anonymous block";
1019  return ExtendedDescription;
1020  }
1021 
1022  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
1023  Out << Prefix;
1024  if (ExtendedDescription && !MD->isUserProvided()) {
1025  if (MD->isExplicitlyDefaulted())
1026  Out << "defaulted ";
1027  else
1028  Out << "implicit ";
1029  }
1030 
1031  if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
1032  if (CD->isDefaultConstructor())
1033  Out << "default ";
1034  else if (CD->isCopyConstructor())
1035  Out << "copy ";
1036  else if (CD->isMoveConstructor())
1037  Out << "move ";
1038 
1039  Out << "constructor";
1040  describeClass(Out, MD->getParent(), " for ");
1041  } else if (isa<CXXDestructorDecl>(MD)) {
1042  if (!MD->isUserProvided()) {
1043  Out << "destructor";
1044  describeClass(Out, MD->getParent(), " for ");
1045  } else {
1046  // Use ~Foo for explicitly-written destructors.
1047  Out << "'" << *MD << "'";
1048  }
1049  } else if (MD->isCopyAssignmentOperator()) {
1050  Out << "copy assignment operator";
1051  describeClass(Out, MD->getParent(), " for ");
1052  } else if (MD->isMoveAssignmentOperator()) {
1053  Out << "move assignment operator";
1054  describeClass(Out, MD->getParent(), " for ");
1055  } else {
1056  if (MD->getParent()->getIdentifier())
1057  Out << "'" << *MD->getParent() << "::" << *MD << "'";
1058  else
1059  Out << "'" << *MD << "'";
1060  }
1061 
1062  return true;
1063  }
1064 
1065  Out << Prefix << '\'' << cast<NamedDecl>(*D) << '\'';
1066  return true;
1067 }
1068 
1069 std::shared_ptr<PathDiagnosticEventPiece>
1071  // We do not produce call enters and call exits for autosynthesized property
1072  // accessors. We do generally produce them for other functions coming from
1073  // the body farm because they may call callbacks that bring us back into
1074  // visible code.
1075  if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
1076  return nullptr;
1077 
1078  SmallString<256> buf;
1079  llvm::raw_svector_ostream Out(buf);
1080 
1081  Out << "Calling ";
1082  describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
1083 
1084  assert(callEnter.asLocation().isValid());
1085  return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
1086 }
1087 
1088 std::shared_ptr<PathDiagnosticEventPiece>
1090  if (!callEnterWithin.asLocation().isValid())
1091  return nullptr;
1092  if (Callee->isImplicit() || !Callee->hasBody())
1093  return nullptr;
1094  if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
1095  if (MD->isDefaulted())
1096  return nullptr;
1097 
1098  SmallString<256> buf;
1099  llvm::raw_svector_ostream Out(buf);
1100 
1101  Out << "Entered call";
1102  describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
1103 
1104  return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
1105 }
1106 
1107 std::shared_ptr<PathDiagnosticEventPiece>
1109  // We do not produce call enters and call exits for autosynthesized property
1110  // accessors. We do generally produce them for other functions coming from
1111  // the body farm because they may call callbacks that bring us back into
1112  // visible code.
1113  if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
1114  return nullptr;
1115 
1116  SmallString<256> buf;
1117  llvm::raw_svector_ostream Out(buf);
1118 
1119  if (!CallStackMessage.empty()) {
1120  Out << CallStackMessage;
1121  } else {
1122  bool DidDescribe = describeCodeDecl(Out, Callee,
1123  /*ExtendedDescription=*/false,
1124  "Returning from ");
1125  if (!DidDescribe)
1126  Out << "Returning to caller";
1127  }
1128 
1129  assert(callReturn.asLocation().isValid());
1130  return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
1131 }
1132 
1133 static void compute_path_size(const PathPieces &pieces, unsigned &size) {
1134  for (const auto &I : pieces) {
1135  const PathDiagnosticPiece *piece = I.get();
1136  if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
1137  compute_path_size(cp->path, size);
1138  else
1139  ++size;
1140  }
1141 }
1142 
1144  unsigned size = 0;
1145  compute_path_size(path, size);
1146  return size;
1147 }
1148 
1149 //===----------------------------------------------------------------------===//
1150 // FoldingSet profiling methods.
1151 //===----------------------------------------------------------------------===//
1152 
1153 void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
1154  ID.AddInteger(Range.getBegin().getRawEncoding());
1155  ID.AddInteger(Range.getEnd().getRawEncoding());
1156  ID.AddInteger(Loc.getRawEncoding());
1157 }
1158 
1159 void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1160  ID.AddInteger((unsigned) getKind());
1161  ID.AddString(str);
1162  // FIXME: Add profiling support for code hints.
1163  ID.AddInteger((unsigned) getDisplayHint());
1164  ArrayRef<SourceRange> Ranges = getRanges();
1165  for (const auto &I : Ranges) {
1166  ID.AddInteger(I.getBegin().getRawEncoding());
1167  ID.AddInteger(I.getEnd().getRawEncoding());
1168  }
1169 }
1170 
1171 void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1173  for (const auto &I : path)
1174  ID.Add(*I);
1175 }
1176 
1177 void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1179  ID.Add(Pos);
1180 }
1181 
1182 void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1184  for (const auto &I : *this)
1185  ID.Add(I);
1186 }
1187 
1188 void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1190  for (const auto &I : subPieces)
1191  ID.Add(*I);
1192 }
1193 
1194 void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
1196 }
1197 
1198 void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
1199  ID.Add(getLocation());
1200  ID.AddString(BugType);
1201  ID.AddString(VerboseDesc);
1202  ID.AddString(Category);
1203 }
1204 
1205 void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1206  Profile(ID);
1207  for (const auto &I : path)
1208  ID.Add(*I);
1209  for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1210  ID.AddString(*I);
1211 }
1212 
1214 
1216  if (!N)
1217  return getMessageForSymbolNotFound();
1218 
1219  ProgramPoint P = N->getLocation();
1220  CallExitEnd CExit = P.castAs<CallExitEnd>();
1221 
1222  // FIXME: Use CallEvent to abstract this over all calls.
1223  const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
1224  const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
1225  if (!CE)
1226  return {};
1227 
1228  // Check if one of the parameters are set to the interesting symbol.
1229  unsigned ArgIndex = 0;
1230  for (CallExpr::const_arg_iterator I = CE->arg_begin(),
1231  E = CE->arg_end(); I != E; ++I, ++ArgIndex){
1232  SVal SV = N->getSVal(*I);
1233 
1234  // Check if the variable corresponding to the symbol is passed by value.
1235  SymbolRef AS = SV.getAsLocSymbol();
1236  if (AS == Sym) {
1237  return getMessageForArg(*I, ArgIndex);
1238  }
1239 
1240  // Check if the parameter is a pointer to the symbol.
1242  // Do not attempt to dereference void*.
1243  if ((*I)->getType()->isVoidPointerType())
1244  continue;
1245  SVal PSV = N->getState()->getSVal(Reg->getRegion());
1246  SymbolRef AS = PSV.getAsLocSymbol();
1247  if (AS == Sym) {
1248  return getMessageForArg(*I, ArgIndex);
1249  }
1250  }
1251  }
1252 
1253  // Check if we are returning the interesting symbol.
1254  SVal SV = N->getSVal(CE);
1255  SymbolRef RetSym = SV.getAsLocSymbol();
1256  if (RetSym == Sym) {
1257  return getMessageForReturn(CE);
1258  }
1259 
1260  return getMessageForSymbolNotFound();
1261 }
1262 
1264  unsigned ArgIndex) {
1265  // Printed parameters start at 1, not 0.
1266  ++ArgIndex;
1267 
1268  SmallString<200> buf;
1269  llvm::raw_svector_ostream os(buf);
1270 
1271  os << Msg << " via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1272  << " parameter";
1273 
1274  return os.str();
1275 }
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:2418
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.
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.
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
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:3290
meta_iterator meta_begin() const
FileID getFileID() const
const Stmt * getTriggerStmt() const
Definition: CFG.h:389
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:1989
StringRef getVerboseDescription() const
static const LocationContext * findTopAutosynthesizedParentContext(const LocationContext *LC)
int Category
Definition: Format.cpp:1575
static bool isInCodeFile(SourceLocation SL, const SourceManager &SM)
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:3016
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
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:3300
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:5354
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.
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:2616
const SourceManager & SM
Definition: Format.cpp:1442
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:3054
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...
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.
const LocationContext * getLocationContext() const
Definition: ProgramPoint.h:180
void Profile(llvm::FoldingSetNodeID &ID) const override
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:13503
const CXXNewExpr * getAllocatorExpr() const
Definition: CFG.h:241
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:2416
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.