clang  5.0.0
PathDiagnostic.cpp
Go to the documentation of this file.
1 //===--- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -*- C++ -*-===//
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/DeclCXX.h"
17 #include "clang/AST/DeclObjC.h"
18 #include "clang/AST/Expr.h"
19 #include "clang/AST/ExprCXX.h"
20 #include "clang/AST/ParentMap.h"
21 #include "clang/AST/StmtCXX.h"
24 #include "llvm/ADT/SmallString.h"
25 #include "llvm/ADT/StringExtras.h"
26 #include "llvm/Support/raw_ostream.h"
27 
28 using namespace clang;
29 using namespace ento;
30 
32  for (auto &P : subPieces) {
33  if (isa<PathDiagnosticEventPiece>(*P))
34  return true;
35  if (auto *MP = dyn_cast<PathDiagnosticMacroPiece>(P.get()))
36  if (MP->containsEvent())
37  return true;
38  }
39  return false;
40 }
41 
42 static StringRef StripTrailingDots(StringRef s) {
43  for (StringRef::size_type i = s.size(); i != 0; --i)
44  if (s[i - 1] != '.')
45  return s.substr(0, i);
46  return "";
47 }
48 
49 PathDiagnosticPiece::PathDiagnosticPiece(StringRef s,
50  Kind k, DisplayHint hint)
51  : str(StripTrailingDots(s)), kind(k), Hint(hint),
52  LastInMainSourceFile(false) {}
53 
54 PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
55  : kind(k), Hint(hint), LastInMainSourceFile(false) {}
56 
63 
64 void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
65  bool ShouldFlattenMacros) const {
66  for (auto &Piece : *this) {
67  switch (Piece->getKind()) {
69  auto &Call = cast<PathDiagnosticCallPiece>(*Piece);
70  if (auto CallEnter = Call.getCallEnterEvent())
71  Current.push_back(std::move(CallEnter));
72  Call.path.flattenTo(Primary, Primary, ShouldFlattenMacros);
73  if (auto callExit = Call.getCallExitEvent())
74  Current.push_back(std::move(callExit));
75  break;
76  }
78  auto &Macro = cast<PathDiagnosticMacroPiece>(*Piece);
79  if (ShouldFlattenMacros) {
80  Macro.subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
81  } else {
82  Current.push_back(Piece);
83  PathPieces NewPath;
84  Macro.subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
85  // FIXME: This probably shouldn't mutate the original path piece.
86  Macro.subPieces = NewPath;
87  }
88  break;
89  }
93  Current.push_back(Piece);
94  break;
95  }
96  }
97 }
98 
100 
101 PathDiagnostic::PathDiagnostic(StringRef CheckName, const Decl *declWithIssue,
102  StringRef bugtype, StringRef verboseDesc,
103  StringRef shortDesc, StringRef category,
104  PathDiagnosticLocation LocationToUnique,
105  const Decl *DeclToUnique)
106  : CheckName(CheckName),
107  DeclWithIssue(declWithIssue),
108  BugType(StripTrailingDots(bugtype)),
109  VerboseDesc(StripTrailingDots(verboseDesc)),
110  ShortDesc(StripTrailingDots(shortDesc)),
111  Category(StripTrailingDots(category)),
112  UniqueingLoc(LocationToUnique),
113  UniqueingDecl(DeclToUnique),
114  path(pathImpl) {}
115 
118  const SourceManager &SMgr) {
119  SourceLocation CallLoc = CP->callEnter.asLocation();
120 
121  // If the call is within a macro, don't do anything (for now).
122  if (CallLoc.isMacroID())
123  return nullptr;
124 
125  assert(SMgr.isInMainFile(CallLoc) &&
126  "The call piece should be in the main file.");
127 
128  // Check if CP represents a path through a function outside of the main file.
129  if (!SMgr.isInMainFile(CP->callEnterWithin.asLocation()))
130  return CP;
131 
132  const PathPieces &Path = CP->path;
133  if (Path.empty())
134  return nullptr;
135 
136  // Check if the last piece in the callee path is a call to a function outside
137  // of the main file.
138  if (PathDiagnosticCallPiece *CPInner =
139  dyn_cast<PathDiagnosticCallPiece>(Path.back().get())) {
140  return getFirstStackedCallToHeaderFile(CPInner, SMgr);
141  }
142 
143  // Otherwise, the last piece is in the main file.
144  return nullptr;
145 }
146 
148  if (path.empty())
149  return;
150 
151  PathDiagnosticPiece *LastP = path.back().get();
152  assert(LastP);
153  const SourceManager &SMgr = LastP->getLocation().getManager();
154 
155  // We only need to check if the report ends inside headers, if the last piece
156  // is a call piece.
157  if (PathDiagnosticCallPiece *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
158  CP = getFirstStackedCallToHeaderFile(CP, SMgr);
159  if (CP) {
160  // Mark the piece.
161  CP->setAsLastInMainSourceFile();
162 
163  // Update the path diagnostic message.
164  const NamedDecl *ND = dyn_cast<NamedDecl>(CP->getCallee());
165  if (ND) {
166  SmallString<200> buf;
167  llvm::raw_svector_ostream os(buf);
168  os << " (within a call to '" << ND->getDeclName() << "')";
169  appendToDesc(os.str());
170  }
171 
172  // Reset the report containing declaration and location.
173  DeclWithIssue = CP->getCaller();
174  Loc = CP->getLocation();
175 
176  return;
177  }
178  }
179 }
180 
181 void PathDiagnosticConsumer::anchor() { }
182 
184  // Delete the contents of the FoldingSet if it isn't empty already.
185  for (llvm::FoldingSet<PathDiagnostic>::iterator it =
186  Diags.begin(), et = Diags.end() ; it != et ; ++it) {
187  delete &*it;
188  }
189 }
190 
192  std::unique_ptr<PathDiagnostic> D) {
193  if (!D || D->path.empty())
194  return;
195 
196  // We need to flatten the locations (convert Stmt* to locations) because
197  // the referenced statements may be freed by the time the diagnostics
198  // are emitted.
199  D->flattenLocations();
200 
201  // If the PathDiagnosticConsumer does not support diagnostics that
202  // cross file boundaries, prune out such diagnostics now.
204  // Verify that the entire path is from the same FileID.
205  FileID FID;
206  const SourceManager &SMgr = D->path.front()->getLocation().getManager();
208  WorkList.push_back(&D->path);
209  SmallString<128> buf;
210  llvm::raw_svector_ostream warning(buf);
211  warning << "warning: Path diagnostic report is not generated. Current "
212  << "output format does not support diagnostics that cross file "
213  << "boundaries. Refer to --analyzer-output for valid output "
214  << "formats\n";
215 
216  while (!WorkList.empty()) {
217  const PathPieces &path = *WorkList.pop_back_val();
218 
219  for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E;
220  ++I) {
221  const PathDiagnosticPiece *piece = I->get();
223 
224  if (FID.isInvalid()) {
225  FID = SMgr.getFileID(L);
226  } else if (SMgr.getFileID(L) != FID) {
227  llvm::errs() << warning.str();
228  return;
229  }
230 
231  // Check the source ranges.
232  ArrayRef<SourceRange> Ranges = piece->getRanges();
233  for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
234  E = Ranges.end(); I != E; ++I) {
235  SourceLocation L = SMgr.getExpansionLoc(I->getBegin());
236  if (!L.isFileID() || SMgr.getFileID(L) != FID) {
237  llvm::errs() << warning.str();
238  return;
239  }
240  L = SMgr.getExpansionLoc(I->getEnd());
241  if (!L.isFileID() || SMgr.getFileID(L) != FID) {
242  llvm::errs() << warning.str();
243  return;
244  }
245  }
246 
247  if (const PathDiagnosticCallPiece *call =
248  dyn_cast<PathDiagnosticCallPiece>(piece)) {
249  WorkList.push_back(&call->path);
250  }
251  else if (const PathDiagnosticMacroPiece *macro =
252  dyn_cast<PathDiagnosticMacroPiece>(piece)) {
253  WorkList.push_back(&macro->subPieces);
254  }
255  }
256  }
257 
258  if (FID.isInvalid())
259  return; // FIXME: Emit a warning?
260  }
261 
262  // Profile the node to see if we already have something matching it
263  llvm::FoldingSetNodeID profile;
264  D->Profile(profile);
265  void *InsertPos = nullptr;
266 
267  if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
268  // Keep the PathDiagnostic with the shorter path.
269  // Note, the enclosing routine is called in deterministic order, so the
270  // results will be consistent between runs (no reason to break ties if the
271  // size is the same).
272  const unsigned orig_size = orig->full_size();
273  const unsigned new_size = D->full_size();
274  if (orig_size <= new_size)
275  return;
276 
277  assert(orig != D.get());
278  Diags.RemoveNode(orig);
279  delete orig;
280  }
281 
282  Diags.InsertNode(D.release());
283 }
284 
285 static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y);
286 
287 static Optional<bool>
292  if (XSL != YSL)
293  return XSL.isBeforeInTranslationUnitThan(YSL);
296  if (XEL != YEL)
297  return XEL.isBeforeInTranslationUnitThan(YEL);
298  return None;
299 }
300 
302  const PathDiagnosticMacroPiece &Y) {
303  return comparePath(X.subPieces, Y.subPieces);
304 }
305 
307  const PathDiagnosticCallPiece &Y) {
308  FullSourceLoc X_CEL = X.callEnter.asLocation();
309  FullSourceLoc Y_CEL = Y.callEnter.asLocation();
310  if (X_CEL != Y_CEL)
311  return X_CEL.isBeforeInTranslationUnitThan(Y_CEL);
314  if (X_CEWL != Y_CEWL)
315  return X_CEWL.isBeforeInTranslationUnitThan(Y_CEWL);
316  FullSourceLoc X_CRL = X.callReturn.asLocation();
317  FullSourceLoc Y_CRL = Y.callReturn.asLocation();
318  if (X_CRL != Y_CRL)
319  return X_CRL.isBeforeInTranslationUnitThan(Y_CRL);
320  return comparePath(X.path, Y.path);
321 }
322 
324  const PathDiagnosticPiece &Y) {
325  if (X.getKind() != Y.getKind())
326  return X.getKind() < Y.getKind();
327 
330  if (XL != YL)
331  return XL.isBeforeInTranslationUnitThan(YL);
332 
333  if (X.getString() != Y.getString())
334  return X.getString() < Y.getString();
335 
336  if (X.getRanges().size() != Y.getRanges().size())
337  return X.getRanges().size() < Y.getRanges().size();
338 
339  const SourceManager &SM = XL.getManager();
340 
341  for (unsigned i = 0, n = X.getRanges().size(); i < n; ++i) {
342  SourceRange XR = X.getRanges()[i];
343  SourceRange YR = Y.getRanges()[i];
344  if (XR != YR) {
345  if (XR.getBegin() != YR.getBegin())
346  return SM.isBeforeInTranslationUnit(XR.getBegin(), YR.getBegin());
347  return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd());
348  }
349  }
350 
351  switch (X.getKind()) {
353  return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X),
354  cast<PathDiagnosticControlFlowPiece>(Y));
357  return None;
359  return compareMacro(cast<PathDiagnosticMacroPiece>(X),
360  cast<PathDiagnosticMacroPiece>(Y));
362  return compareCall(cast<PathDiagnosticCallPiece>(X),
363  cast<PathDiagnosticCallPiece>(Y));
364  }
365  llvm_unreachable("all cases handled");
366 }
367 
369  if (X.size() != Y.size())
370  return X.size() < Y.size();
371 
372  PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
373  PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
374 
375  for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) {
376  Optional<bool> b = comparePiece(**X_I, **Y_I);
377  if (b.hasValue())
378  return b.getValue();
379  }
380 
381  return None;
382 }
383 
384 static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
387  if (XL != YL)
388  return XL.isBeforeInTranslationUnitThan(YL);
389  if (X.getBugType() != Y.getBugType())
390  return X.getBugType() < Y.getBugType();
391  if (X.getCategory() != Y.getCategory())
392  return X.getCategory() < Y.getCategory();
396  return X.getShortDescription() < Y.getShortDescription();
397  if (X.getDeclWithIssue() != Y.getDeclWithIssue()) {
398  const Decl *XD = X.getDeclWithIssue();
399  if (!XD)
400  return true;
401  const Decl *YD = Y.getDeclWithIssue();
402  if (!YD)
403  return false;
404  SourceLocation XDL = XD->getLocation();
405  SourceLocation YDL = YD->getLocation();
406  if (XDL != YDL) {
407  const SourceManager &SM = XL.getManager();
408  return SM.isBeforeInTranslationUnit(XDL, YDL);
409  }
410  }
413  if (XE - XI != YE - YI)
414  return (XE - XI) < (YE - YI);
415  for ( ; XI != XE ; ++XI, ++YI) {
416  if (*XI != *YI)
417  return (*XI) < (*YI);
418  }
420  assert(b.hasValue());
421  return b.getValue();
422 }
423 
426  if (flushed)
427  return;
428 
429  flushed = true;
430 
431  std::vector<const PathDiagnostic *> BatchDiags;
432  for (llvm::FoldingSet<PathDiagnostic>::iterator it = Diags.begin(),
433  et = Diags.end(); it != et; ++it) {
434  const PathDiagnostic *D = &*it;
435  BatchDiags.push_back(D);
436  }
437 
438  // Sort the diagnostics so that they are always emitted in a deterministic
439  // order.
440  int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
441  [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
442  assert(*X != *Y && "PathDiagnostics not uniqued!");
443  if (compare(**X, **Y))
444  return -1;
445  assert(compare(**Y, **X) && "Not a total order!");
446  return 1;
447  };
448  array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
449 
450  FlushDiagnosticsImpl(BatchDiags, Files);
451 
452  // Delete the flushed diagnostics.
453  for (std::vector<const PathDiagnostic *>::iterator it = BatchDiags.begin(),
454  et = BatchDiags.end(); it != et; ++it) {
455  const PathDiagnostic *D = *it;
456  delete D;
457  }
458 
459  // Clear out the FoldingSet.
460  Diags.clear();
461 }
462 
464  for (PDFileEntry &Entry : Set)
465  Entry.~PDFileEntry();
466 }
467 
469  StringRef ConsumerName,
470  StringRef FileName) {
471  llvm::FoldingSetNodeID NodeID;
472  NodeID.Add(PD);
473  void *InsertPos;
474  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
475  if (!Entry) {
476  Entry = Alloc.Allocate<PDFileEntry>();
477  Entry = new (Entry) PDFileEntry(NodeID);
478  Set.InsertNode(Entry, InsertPos);
479  }
480 
481  // Allocate persistent storage for the file name.
482  char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
483  memcpy(FileName_cstr, FileName.data(), FileName.size());
484 
485  Entry->files.push_back(std::make_pair(ConsumerName,
486  StringRef(FileName_cstr,
487  FileName.size())));
488 }
489 
492  llvm::FoldingSetNodeID NodeID;
493  NodeID.Add(PD);
494  void *InsertPos;
495  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
496  if (!Entry)
497  return nullptr;
498  return &Entry->files;
499 }
500 
501 //===----------------------------------------------------------------------===//
502 // PathDiagnosticLocation methods.
503 //===----------------------------------------------------------------------===//
504 
507  bool UseEnd = false) {
508  SourceLocation L = UseEnd ? S->getLocEnd() : S->getLocStart();
509  assert(!LAC.isNull() && "A valid LocationContext or AnalysisDeclContext should "
510  "be passed to PathDiagnosticLocation upon creation.");
511 
512  // S might be a temporary statement that does not have a location in the
513  // source code, so find an enclosing statement and use its location.
514  if (!L.isValid()) {
515  AnalysisDeclContext *ADC;
516  if (LAC.is<const LocationContext*>())
517  ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext();
518  else
519  ADC = LAC.get<AnalysisDeclContext*>();
520 
521  ParentMap &PM = ADC->getParentMap();
522 
523  const Stmt *Parent = S;
524  do {
525  Parent = PM.getParent(Parent);
526 
527  // In rare cases, we have implicit top-level expressions,
528  // such as arguments for implicit member initializers.
529  // In this case, fall back to the start of the body (even if we were
530  // asked for the statement end location).
531  if (!Parent) {
532  const Stmt *Body = ADC->getBody();
533  if (Body)
534  L = Body->getLocStart();
535  else
536  L = ADC->getDecl()->getLocEnd();
537  break;
538  }
539 
540  L = UseEnd ? Parent->getLocEnd() : Parent->getLocStart();
541  } while (!L.isValid());
542  }
543 
544  return L;
545 }
546 
549  const LocationContext *CallerCtx,
550  const SourceManager &SM) {
551  const CFGBlock &Block = *SFC->getCallSiteBlock();
552  CFGElement Source = Block[SFC->getIndex()];
553 
554  switch (Source.getKind()) {
556  return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
557  SM, CallerCtx);
559  const CFGInitializer &Init = Source.castAs<CFGInitializer>();
561  SM, CallerCtx);
562  }
564  const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
566  SM, CallerCtx);
567  }
568  case CFGElement::DeleteDtor: {
569  const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
570  return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
571  }
573  case CFGElement::MemberDtor: {
574  const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
575  if (const Stmt *CallerBody = CallerInfo->getBody())
576  return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
577  return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
578  }
582  llvm_unreachable("not yet implemented!");
583  }
584 
585  llvm_unreachable("Unknown CFGElement kind");
586 }
587 
590  const SourceManager &SM) {
591  return PathDiagnosticLocation(D->getLocStart(), SM, SingleLocK);
592 }
593 
596  const SourceManager &SM,
599  SM, SingleLocK);
600 }
601 
604  const SourceManager &SM,
606  if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(S))
607  return createEndBrace(CS, SM);
608  return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
609  SM, SingleLocK);
610 }
611 
614  const SourceManager &SM) {
615  return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
616 }
617 
620  const ConditionalOperator *CO,
621  const SourceManager &SM) {
622  return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
623 }
624 
625 
628  const SourceManager &SM) {
629  return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
630 }
631 
634  const SourceManager &SM) {
635  SourceLocation L = CS->getLBracLoc();
636  return PathDiagnosticLocation(L, SM, SingleLocK);
637 }
638 
641  const SourceManager &SM) {
642  SourceLocation L = CS->getRBracLoc();
643  return PathDiagnosticLocation(L, SM, SingleLocK);
644 }
645 
648  const SourceManager &SM) {
649  // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
650  if (const CompoundStmt *CS =
651  dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
652  if (!CS->body_empty()) {
653  SourceLocation Loc = (*CS->body_begin())->getLocStart();
654  return PathDiagnosticLocation(Loc, SM, SingleLocK);
655  }
656 
657  return PathDiagnosticLocation();
658 }
659 
662  const SourceManager &SM) {
663  SourceLocation L = LC->getDecl()->getBodyRBrace();
664  return PathDiagnosticLocation(L, SM, SingleLocK);
665 }
666 
669  const SourceManager &SMng) {
670  const Stmt* S = nullptr;
671  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
672  const CFGBlock *BSrc = BE->getSrc();
673  S = BSrc->getTerminatorCondition();
674  } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
675  S = SP->getStmt();
678  } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
679  return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
680  SMng);
681  } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
682  return PathDiagnosticLocation(PIE->getLocation(), SMng);
683  } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
684  return getLocationForCaller(CE->getCalleeContext(),
685  CE->getLocationContext(),
686  SMng);
687  } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
688  return getLocationForCaller(CEE->getCalleeContext(),
689  CEE->getLocationContext(),
690  SMng);
691  } else {
692  llvm_unreachable("Unexpected ProgramPoint");
693  }
694 
695  return PathDiagnosticLocation(S, SMng, P.getLocationContext());
696 }
697 
698 static const LocationContext *
701  const LocationContext *ParentLC = LC->getParent();
702  assert(ParentLC && "We don't start analysis from autosynthesized code");
703  while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
704  LC = ParentLC;
705  ParentLC = LC->getParent();
706  assert(ParentLC && "We don't start analysis from autosynthesized code");
707  }
708  return LC;
709 }
710 
712  // We cannot place diagnostics on autosynthesized code.
713  // Put them onto the call site through which we jumped into autosynthesized
714  // code for the first time.
715  const LocationContext *LC = N->getLocationContext();
717  // It must be a stack frame because we only autosynthesize functions.
718  return cast<StackFrameContext>(findTopAutosynthesizedParentContext(LC))
719  ->getCallSite();
720  }
721  // Otherwise, see if the node's program point directly points to a statement.
722  ProgramPoint P = N->getLocation();
723  if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
724  return SP->getStmt();
725  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>())
726  return BE->getSrc()->getTerminator();
727  if (Optional<CallEnter> CE = P.getAs<CallEnter>())
728  return CE->getCallExpr();
729  if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>())
730  return CEE->getCalleeContext()->getCallSite();
732  return PIPP->getInitializer()->getInit();
733 
734  return nullptr;
735 }
736 
738  for (N = N->getFirstSucc(); N; N = N->getFirstSucc()) {
739  if (const Stmt *S = getStmt(N)) {
740  // Check if the statement is '?' or '&&'/'||'. These are "merges",
741  // not actual statement points.
742  switch (S->getStmtClass()) {
743  case Stmt::ChooseExprClass:
744  case Stmt::BinaryConditionalOperatorClass:
745  case Stmt::ConditionalOperatorClass:
746  continue;
747  case Stmt::BinaryOperatorClass: {
748  BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
749  if (Op == BO_LAnd || Op == BO_LOr)
750  continue;
751  break;
752  }
753  default:
754  break;
755  }
756  // We found the statement, so return it.
757  return S;
758  }
759  }
760 
761  return nullptr;
762 }
763 
766  const SourceManager &SM) {
767  assert(N && "Cannot create a location with a null node.");
768  const Stmt *S = getStmt(N);
769 
770  if (!S) {
771  // If this is an implicit call, return the implicit call point location.
773  return PathDiagnosticLocation(PIE->getLocation(), SM);
774  S = getNextStmt(N);
775  }
776 
777  if (S) {
778  ProgramPoint P = N->getLocation();
779  const LocationContext *LC = N->getLocationContext();
780 
781  // For member expressions, return the location of the '.' or '->'.
782  if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
784 
785  // For binary operators, return the location of the operator.
786  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
788 
790  return PathDiagnosticLocation::createEnd(S, SM, LC);
791 
792  if (S->getLocStart().isValid())
793  return PathDiagnosticLocation(S, SM, LC);
795  }
796 
797  return createDeclEnd(N->getLocationContext(), SM);
798 }
799 
801  const PathDiagnosticLocation &PDL) {
802  FullSourceLoc L = PDL.asLocation();
803  return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
804 }
805 
807  PathDiagnosticLocation::genLocation(SourceLocation L,
808  LocationOrAnalysisDeclContext LAC) const {
809  assert(isValid());
810  // Note that we want a 'switch' here so that the compiler can warn us in
811  // case we add more cases.
812  switch (K) {
813  case SingleLocK:
814  case RangeK:
815  break;
816  case StmtK:
817  // Defensive checking.
818  if (!S)
819  break;
821  const_cast<SourceManager&>(*SM));
822  case DeclK:
823  // Defensive checking.
824  if (!D)
825  break;
826  return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
827  }
828 
829  return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
830 }
831 
833  PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
834  assert(isValid());
835  // Note that we want a 'switch' here so that the compiler can warn us in
836  // case we add more cases.
837  switch (K) {
838  case SingleLocK:
839  return PathDiagnosticRange(SourceRange(Loc,Loc), true);
840  case RangeK:
841  break;
842  case StmtK: {
843  const Stmt *S = asStmt();
844  switch (S->getStmtClass()) {
845  default:
846  break;
847  case Stmt::DeclStmtClass: {
848  const DeclStmt *DS = cast<DeclStmt>(S);
849  if (DS->isSingleDecl()) {
850  // Should always be the case, but we'll be defensive.
851  return SourceRange(DS->getLocStart(),
852  DS->getSingleDecl()->getLocation());
853  }
854  break;
855  }
856  // FIXME: Provide better range information for different
857  // terminators.
858  case Stmt::IfStmtClass:
859  case Stmt::WhileStmtClass:
860  case Stmt::DoStmtClass:
861  case Stmt::ForStmtClass:
862  case Stmt::ChooseExprClass:
863  case Stmt::IndirectGotoStmtClass:
864  case Stmt::SwitchStmtClass:
865  case Stmt::BinaryConditionalOperatorClass:
866  case Stmt::ConditionalOperatorClass:
867  case Stmt::ObjCForCollectionStmtClass: {
869  return SourceRange(L, L);
870  }
871  }
872  SourceRange R = S->getSourceRange();
873  if (R.isValid())
874  return R;
875  break;
876  }
877  case DeclK:
878  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
879  return MD->getSourceRange();
880  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
881  if (Stmt *Body = FD->getBody())
882  return Body->getSourceRange();
883  }
884  else {
885  SourceLocation L = D->getLocation();
886  return PathDiagnosticRange(SourceRange(L, L), true);
887  }
888  }
889 
890  return SourceRange(Loc,Loc);
891 }
892 
894  if (K == StmtK) {
895  K = RangeK;
896  S = nullptr;
897  D = nullptr;
898  }
899  else if (K == DeclK) {
900  K = SingleLocK;
901  S = nullptr;
902  D = nullptr;
903  }
904 }
905 
906 //===----------------------------------------------------------------------===//
907 // Manipulation of PathDiagnosticCallPieces.
908 //===----------------------------------------------------------------------===//
909 
910 std::shared_ptr<PathDiagnosticCallPiece>
912  const SourceManager &SM) {
913  const Decl *caller = CE.getLocationContext()->getDecl();
915  CE.getLocationContext(),
916  SM);
917  return std::shared_ptr<PathDiagnosticCallPiece>(
918  new PathDiagnosticCallPiece(caller, pos));
919 }
920 
923  const Decl *caller) {
924  std::shared_ptr<PathDiagnosticCallPiece> C(
925  new PathDiagnosticCallPiece(path, caller));
926  path.clear();
927  auto *R = C.get();
928  path.push_front(std::move(C));
929  return R;
930 }
931 
933  const SourceManager &SM) {
934  const StackFrameContext *CalleeCtx = CE.getCalleeContext();
935  Callee = CalleeCtx->getDecl();
936 
937  callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
938  callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
939 
940  // Autosynthesized property accessors are special because we'd never
941  // pop back up to non-autosynthesized code until we leave them.
942  // This is not generally true for autosynthesized callees, which may call
943  // non-autosynthesized callbacks.
944  // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
945  // defaults to false.
946  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Callee))
947  IsCalleeAnAutosynthesizedPropertyAccessor = (
948  MD->isPropertyAccessor() &&
950 }
951 
952 static inline void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
953  StringRef Prefix = StringRef()) {
954  if (!D->getIdentifier())
955  return;
956  Out << Prefix << '\'' << *D << '\'';
957 }
958 
959 static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
960  bool ExtendedDescription,
961  StringRef Prefix = StringRef()) {
962  if (!D)
963  return false;
964 
965  if (isa<BlockDecl>(D)) {
966  if (ExtendedDescription)
967  Out << Prefix << "anonymous block";
968  return ExtendedDescription;
969  }
970 
971  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
972  Out << Prefix;
973  if (ExtendedDescription && !MD->isUserProvided()) {
974  if (MD->isExplicitlyDefaulted())
975  Out << "defaulted ";
976  else
977  Out << "implicit ";
978  }
979 
980  if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(MD)) {
981  if (CD->isDefaultConstructor())
982  Out << "default ";
983  else if (CD->isCopyConstructor())
984  Out << "copy ";
985  else if (CD->isMoveConstructor())
986  Out << "move ";
987 
988  Out << "constructor";
989  describeClass(Out, MD->getParent(), " for ");
990 
991  } else if (isa<CXXDestructorDecl>(MD)) {
992  if (!MD->isUserProvided()) {
993  Out << "destructor";
994  describeClass(Out, MD->getParent(), " for ");
995  } else {
996  // Use ~Foo for explicitly-written destructors.
997  Out << "'" << *MD << "'";
998  }
999 
1000  } else if (MD->isCopyAssignmentOperator()) {
1001  Out << "copy assignment operator";
1002  describeClass(Out, MD->getParent(), " for ");
1003 
1004  } else if (MD->isMoveAssignmentOperator()) {
1005  Out << "move assignment operator";
1006  describeClass(Out, MD->getParent(), " for ");
1007 
1008  } else {
1009  if (MD->getParent()->getIdentifier())
1010  Out << "'" << *MD->getParent() << "::" << *MD << "'";
1011  else
1012  Out << "'" << *MD << "'";
1013  }
1014 
1015  return true;
1016  }
1017 
1018  Out << Prefix << '\'' << cast<NamedDecl>(*D) << '\'';
1019  return true;
1020 }
1021 
1022 std::shared_ptr<PathDiagnosticEventPiece>
1024  // We do not produce call enters and call exits for autosynthesized property
1025  // accessors. We do generally produce them for other functions coming from
1026  // the body farm because they may call callbacks that bring us back into
1027  // visible code.
1028  if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
1029  return nullptr;
1030 
1031  SmallString<256> buf;
1032  llvm::raw_svector_ostream Out(buf);
1033 
1034  Out << "Calling ";
1035  describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
1036 
1037  assert(callEnter.asLocation().isValid());
1038  return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
1039 }
1040 
1041 std::shared_ptr<PathDiagnosticEventPiece>
1043  if (!callEnterWithin.asLocation().isValid())
1044  return nullptr;
1045  if (Callee->isImplicit() || !Callee->hasBody())
1046  return nullptr;
1047  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee))
1048  if (MD->isDefaulted())
1049  return nullptr;
1050 
1051  SmallString<256> buf;
1052  llvm::raw_svector_ostream Out(buf);
1053 
1054  Out << "Entered call";
1055  describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
1056 
1057  return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
1058 }
1059 
1060 std::shared_ptr<PathDiagnosticEventPiece>
1062  // We do not produce call enters and call exits for autosynthesized property
1063  // accessors. We do generally produce them for other functions coming from
1064  // the body farm because they may call callbacks that bring us back into
1065  // visible code.
1066  if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
1067  return nullptr;
1068 
1069  SmallString<256> buf;
1070  llvm::raw_svector_ostream Out(buf);
1071 
1072  if (!CallStackMessage.empty()) {
1073  Out << CallStackMessage;
1074  } else {
1075  bool DidDescribe = describeCodeDecl(Out, Callee,
1076  /*ExtendedDescription=*/false,
1077  "Returning from ");
1078  if (!DidDescribe)
1079  Out << "Returning to caller";
1080  }
1081 
1082  assert(callReturn.asLocation().isValid());
1083  return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
1084 }
1085 
1086 static void compute_path_size(const PathPieces &pieces, unsigned &size) {
1087  for (PathPieces::const_iterator it = pieces.begin(),
1088  et = pieces.end(); it != et; ++it) {
1089  const PathDiagnosticPiece *piece = it->get();
1090  if (const PathDiagnosticCallPiece *cp =
1091  dyn_cast<PathDiagnosticCallPiece>(piece)) {
1092  compute_path_size(cp->path, size);
1093  }
1094  else
1095  ++size;
1096  }
1097 }
1098 
1100  unsigned size = 0;
1101  compute_path_size(path, size);
1102  return size;
1103 }
1104 
1105 //===----------------------------------------------------------------------===//
1106 // FoldingSet profiling methods.
1107 //===----------------------------------------------------------------------===//
1108 
1109 void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
1110  ID.AddInteger(Range.getBegin().getRawEncoding());
1111  ID.AddInteger(Range.getEnd().getRawEncoding());
1112  ID.AddInteger(Loc.getRawEncoding());
1113 }
1114 
1115 void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1116  ID.AddInteger((unsigned) getKind());
1117  ID.AddString(str);
1118  // FIXME: Add profiling support for code hints.
1119  ID.AddInteger((unsigned) getDisplayHint());
1120  ArrayRef<SourceRange> Ranges = getRanges();
1121  for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
1122  I != E; ++I) {
1123  ID.AddInteger(I->getBegin().getRawEncoding());
1124  ID.AddInteger(I->getEnd().getRawEncoding());
1125  }
1126 }
1127 
1128 void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1130  for (PathPieces::const_iterator it = path.begin(),
1131  et = path.end(); it != et; ++it) {
1132  ID.Add(**it);
1133  }
1134 }
1135 
1136 void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1138  ID.Add(Pos);
1139 }
1140 
1141 void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1143  for (const_iterator I = begin(), E = end(); I != E; ++I)
1144  ID.Add(*I);
1145 }
1146 
1147 void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1149  for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end();
1150  I != E; ++I)
1151  ID.Add(**I);
1152 }
1153 
1154 void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
1156 }
1157 
1158 void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
1159  ID.Add(getLocation());
1160  ID.AddString(BugType);
1161  ID.AddString(VerboseDesc);
1162  ID.AddString(Category);
1163 }
1164 
1165 void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1166  Profile(ID);
1167  for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E; ++I)
1168  ID.Add(**I);
1169  for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1170  ID.AddString(*I);
1171 }
1172 
1174 
1176  ProgramPoint P = N->getLocation();
1177  CallExitEnd CExit = P.castAs<CallExitEnd>();
1178 
1179  // FIXME: Use CallEvent to abstract this over all calls.
1180  const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
1181  const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite);
1182  if (!CE)
1183  return "";
1184 
1185  if (!N)
1186  return getMessageForSymbolNotFound();
1187 
1188  // Check if one of the parameters are set to the interesting symbol.
1190  const LocationContext *LCtx = N->getLocationContext();
1191  unsigned ArgIndex = 0;
1193  E = CE->arg_end(); I != E; ++I, ++ArgIndex){
1194  SVal SV = State->getSVal(*I, LCtx);
1195 
1196  // Check if the variable corresponding to the symbol is passed by value.
1197  SymbolRef AS = SV.getAsLocSymbol();
1198  if (AS == Sym) {
1199  return getMessageForArg(*I, ArgIndex);
1200  }
1201 
1202  // Check if the parameter is a pointer to the symbol.
1204  SVal PSV = State->getSVal(Reg->getRegion());
1205  SymbolRef AS = PSV.getAsLocSymbol();
1206  if (AS == Sym) {
1207  return getMessageForArg(*I, ArgIndex);
1208  }
1209  }
1210  }
1211 
1212  // Check if we are returning the interesting symbol.
1213  SVal SV = State->getSVal(CE, LCtx);
1214  SymbolRef RetSym = SV.getAsLocSymbol();
1215  if (RetSym == Sym) {
1216  return getMessageForReturn(CE);
1217  }
1218 
1219  return getMessageForSymbolNotFound();
1220 }
1221 
1223  unsigned ArgIndex) {
1224  // Printed parameters start at 1, not 0.
1225  ++ArgIndex;
1226 
1227  SmallString<200> buf;
1228  llvm::raw_svector_ostream os(buf);
1229 
1230  os << Msg << " via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1231  << " parameter";
1232 
1233  return os.str();
1234 }
SourceLocation getEnd() const
StmtClass getStmtClass() const
Definition: Stmt.h:361
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Definition: Decl.h:1618
static Optional< bool > compareMacro(const PathDiagnosticMacroPiece &X, const PathDiagnosticMacroPiece &Y)
bool isMacroID() const
static void compute_path_size(const PathPieces &pieces, unsigned &size)
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
Definition: Decl.h:232
std::deque< std::string >::const_iterator meta_iterator
Stmt - This represents one statement.
Definition: Stmt.h:60
const StackFrameContext * getCalleeContext() const
Definition: ProgramPoint.h:594
Defines the SourceManager interface.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:81
Represents a point when we begin processing an inlined call.
Definition: ProgramPoint.h:584
static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the beginning of the compound statement.
StringRef getCategory() const
StringRef P
std::shared_ptr< PathDiagnosticEventPiece > getCallEnterWithinCallerEvent() const
const SourceManager & getManager() const
CFGDeleteDtor - Represents C++ object destructor generated from a call to delete. ...
Definition: CFG.h:242
virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex)
Produces the message of the following form: 'Msg via Nth parameter'.
Represents a program point just before an implicit call event.
Definition: ProgramPoint.h:551
const CXXDeleteExpr * getDeleteExpr() const
Definition: CFG.h:252
SourceLocation getOperatorLoc() const
Definition: Expr.h:3005
SourceLocation getLocEnd() const LLVM_READONLY
Definition: DeclBase.h:403
static std::shared_ptr< PathDiagnosticCallPiece > construct(const ExplodedNode *N, const CallExitEnd &CE, const SourceManager &SM)
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2329
static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the end of the compound statement.
ArrayRef< SourceRange > getRanges() const
Return the SourceRanges associated with this PathDiagnosticPiece.
PathDiagnosticLocation getLocation() const
Expr * getInit() const
Get the initializer.
Definition: DeclCXX.h:2299
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:113
std::shared_ptr< PathDiagnosticEventPiece > getCallExitEvent() const
const Decl * getDeclWithIssue() const
Return the semantic context where an issue occurred.
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.
FullSourceLoc asLocation() const
Symbolic value.
Definition: SymExpr.h:29
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
bool isBodyAutosynthesized() const
Checks if the body of the Decl is generated by the BodyFarm.
LineState State
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:218
bool isFileID() const
AnalysisDeclContext * getAnalysisDeclContext() const
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
Definition: SVals.cpp:74
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type...
Definition: CFG.h:89
static const LocationContext * findTopAutosynthesizedParentContext(const LocationContext *LC)
int Category
Definition: Format.cpp:1304
SourceLocation getLBracLoc() const
Definition: Stmt.h:653
Optional< T > getLocationAs() const LLVM_LVALUE_FUNCTION
virtual void Profile(llvm::FoldingSetNodeID &ID) const
static PathDiagnosticCallPiece * getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP, const SourceManager &SMgr)
BinaryOperatorKind
llvm::FoldingSet< PathDiagnostic > Diags
std::vector< PathDiagnosticLocationPair >::const_iterator const_iterator
unsigned getIndex() const
void Profile(llvm::FoldingSetNodeID &ID) const override
const CFGBlock * getCallSiteBlock() const
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:2967
const Stmt * getCallSite() const
std::string getMessage(const ExplodedNode *N) override
Search the call expression for the symbol Sym and dispatch the 'getMessageForX()' methods to construc...
Represents a point after we ran remove dead bindings AFTER processing the given statement.
Definition: ProgramPoint.h:457
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)
const Decl * getDecl() const
meta_iterator meta_begin() const
detail::InMemoryDirectory::const_iterator I
virtual PathDiagnosticLocation getLocation() const =0
const Stmt * getTriggerStmt() const
Definition: CFG.h:228
static SourceLocation getValidSourceLocation(const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEnd=false)
arg_iterator arg_end()
Definition: Expr.h:2306
const LocationContext * getLocationContext() const
static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME, const SourceManager &SM)
For member expressions, return the location of the '.
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:3245
Const iterator for iterating over Stmt * arrays that contain only Expr *.
Definition: Stmt.h:329
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:575
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
SourceLocation getLocEnd() const LLVM_READONLY
Definition: Stmt.cpp:270
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
CFGBlock - Represents a single basic block in a source-level CFG.
Definition: CFG.h:377
PDFileEntry::ConsumerFiles * getFiles(const PathDiagnostic &PD)
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
Definition: DeclBase.cpp:851
Stmt * getBody() const
Get the body of the Declaration.
Represents a point when we finish the call exit sequence (for inlined call).
Definition: ProgramPoint.h:638
Expr - This represents one expression.
Definition: Expr.h:105
const ProgramStateRef & getState() const
void FullProfile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, including its path.
Stmt * getTerminatorCondition(bool StripParens=true)
Definition: CFG.cpp:4714
static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y)
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
StringRef getShortDescription() const
const SourceManager & getManager() const
CXXCtorInitializer * getInitializer() const
Definition: CFG.h:140
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:100
const ExplodedNode * getFirstSucc() const
PathDiagnosticLocation getEndLocation() 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.
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type...
Definition: ProgramPoint.h:139
void resetDiagnosticLocationToMainFile()
If the last piece of the report point to the header file, resets the location of the report to be the...
std::vector< std::pair< StringRef, StringRef > > ConsumerFiles
DeclarationName getDeclName() const
getDeclName - Get the actual, stored name of the declaration, which may be a special name...
Definition: Decl.h:258
std::shared_ptr< PathDiagnosticEventPiece > getCallEnterEvent() const
virtual bool supportsCrossFileDiagnostics() const
Return true if the PathDiagnosticConsumer supports individual PathDiagnostics that span multiple file...
PathDiagnosticLocation getStartLocation() const
const SourceManager & SM
Definition: Format.cpp:1293
static Optional< bool > comparePiece(const PathDiagnosticPiece &X, const PathDiagnosticPiece &Y)
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
meta_iterator meta_end() const
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
SourceLocation getLocStart() const LLVM_READONLY
Definition: DeclBase.h:400
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.
#define false
Definition: stdbool.h:33
StringRef FileName
Definition: Format.cpp:1465
virtual void FlushDiagnosticsImpl(std::vector< const PathDiagnostic * > &Diags, FilesMade *filesMade)=0
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
StringRef getVerboseDescription() const
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl. ...
Definition: Stmt.h:481
const std::string ID
bool isValid() const
void Profile(llvm::FoldingSetNodeID &ID) const
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:467
void setCallee(const CallEnter &CE, const SourceManager &SM)
static PathDiagnosticLocation createConditionalColonLoc(const ConditionalOperator *CO, const SourceManager &SM)
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:1903
const Stmt * getStmt() const
Definition: CFG.h:121
static bool describeCodeDecl(raw_ostream &Out, const Decl *D, bool ExtendedDescription, StringRef Prefix=StringRef())
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:63
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:948
static PathDiagnosticLocation createEnd(const Stmt *S, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)
Create a location for the end of the statement.
const StackFrameContext * getCalleeContext() const
Definition: ProgramPoint.h:645
const Decl * getDecl() const
SourceLocation getBegin() const
const Decl * getSingleDecl() const
Definition: Stmt.h:485
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
ConsumerFiles files
A vector of <consumer,file> pairs.
const LocationContext * getParent() const
SourceLocation getLocStart() const LLVM_READONLY
Definition: Stmt.h:497
Represents a program point just after an implicit call event.
Definition: ProgramPoint.h:568
static void describeClass(raw_ostream &Out, const CXXRecordDecl *D, StringRef Prefix=StringRef())
const LocationContext * getLocationContext() const
Definition: ProgramPoint.h:178
void FlushDiagnostics(FilesMade *FilesMade)
BinaryOperator::Opcode getOpcode(const SymExpr *SE)
static Optional< bool > compareCall(const PathDiagnosticCallPiece &X, const PathDiagnosticCallPiece &Y)
detail::InMemoryDirectory::const_iterator E
void Profile(llvm::FoldingSetNodeID &ID) const override
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:150
void appendToDesc(StringRef S)
SourceLocation getMemberLoc() const
getMemberLoc - Return the location of the "member", in X->F, it is the location of 'F'...
Definition: Expr.h:2578
void Profile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, independent of the path it references.
bool isInvalid() const
arg_iterator arg_begin()
Definition: Expr.h:2305
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:13074
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:2378
bool isBeforeInTranslationUnitThan(SourceLocation Loc) const
Determines the order of 2 source locations in the translation unit.
FormatToken * Current
Represents a C++ struct/union/class.
Definition: DeclCXX.h:267
Kind getKind() const
Definition: CFG.h:109
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:54
static StringRef StripTrailingDots(StringRef s)
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Definition: DiagnosticIDs.h:44
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:245
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2206
A SourceLocation and its associated SourceManager.
PathDiagnosticLocation callEnterWithin
SourceLocation getRBracLoc() const
Definition: Stmt.h:654
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:897
void Profile(llvm::FoldingSetNodeID &ID) const override
StringRef getBugType() const
void addDiagnostic(const PathDiagnostic &PD, StringRef ConsumerName, StringRef fileName)
FullSourceLoc getExpansionLoc() const
CFGInitializer - Represents C++ base or member initializer from constructor's initialization list...
Definition: CFG.h:135
A trivial tuple used to represent a source range.
SourceLocation getLocation() const
Definition: DeclBase.h:407
NamedDecl - This represents a decl with a name.
Definition: Decl.h:213
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
SourceLocation getLocStart() const LLVM_READONLY
Definition: Stmt.cpp:257
static Optional< bool > compareControlFlow(const PathDiagnosticControlFlowPiece &X, const PathDiagnosticControlFlowPiece &Y)
This class handles loading and caching of source files into memory.
SourceLocation getColonLoc() const
Definition: Expr.h:3235
unsigned full_size()
Return the unrolled size of the path.
void Profile(llvm::FoldingSetNodeID &ID) const override