clang  6.0.0svn
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.
203  if (!supportsCrossFileDiagnostics()) {
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 
368 static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) {
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  }
581  llvm_unreachable("not yet implemented!");
584  llvm_unreachable("CFGElement kind should not be on callsite!");
585  }
586 
587  llvm_unreachable("Unknown CFGElement kind");
588 }
589 
592  const SourceManager &SM) {
593  return PathDiagnosticLocation(D->getLocStart(), SM, SingleLocK);
594 }
595 
598  const SourceManager &SM,
601  SM, SingleLocK);
602 }
603 
606  const SourceManager &SM,
608  if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(S))
609  return createEndBrace(CS, SM);
610  return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
611  SM, SingleLocK);
612 }
613 
616  const SourceManager &SM) {
617  return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
618 }
619 
622  const ConditionalOperator *CO,
623  const SourceManager &SM) {
624  return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
625 }
626 
627 
630  const SourceManager &SM) {
631  return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
632 }
633 
636  const SourceManager &SM) {
637  SourceLocation L = CS->getLBracLoc();
638  return PathDiagnosticLocation(L, SM, SingleLocK);
639 }
640 
643  const SourceManager &SM) {
644  SourceLocation L = CS->getRBracLoc();
645  return PathDiagnosticLocation(L, SM, SingleLocK);
646 }
647 
650  const SourceManager &SM) {
651  // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
652  if (const CompoundStmt *CS =
653  dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
654  if (!CS->body_empty()) {
655  SourceLocation Loc = (*CS->body_begin())->getLocStart();
656  return PathDiagnosticLocation(Loc, SM, SingleLocK);
657  }
658 
659  return PathDiagnosticLocation();
660 }
661 
664  const SourceManager &SM) {
665  SourceLocation L = LC->getDecl()->getBodyRBrace();
666  return PathDiagnosticLocation(L, SM, SingleLocK);
667 }
668 
671  const SourceManager &SMng) {
672  const Stmt* S = nullptr;
673  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
674  const CFGBlock *BSrc = BE->getSrc();
675  S = BSrc->getTerminatorCondition();
676  } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
677  S = SP->getStmt();
680  } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
681  return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
682  SMng);
683  } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
684  return PathDiagnosticLocation(PIE->getLocation(), SMng);
685  } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
686  return getLocationForCaller(CE->getCalleeContext(),
687  CE->getLocationContext(),
688  SMng);
689  } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
690  return getLocationForCaller(CEE->getCalleeContext(),
691  CEE->getLocationContext(),
692  SMng);
693  } else if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
694  CFGElement BlockFront = BE->getBlock()->front();
695  if (auto StmtElt = BlockFront.getAs<CFGStmt>()) {
696  return PathDiagnosticLocation(StmtElt->getStmt()->getLocStart(), SMng);
697  } else if (auto NewAllocElt = BlockFront.getAs<CFGNewAllocator>()) {
698  return PathDiagnosticLocation(
699  NewAllocElt->getAllocatorExpr()->getLocStart(), SMng);
700  }
701  llvm_unreachable("Unexpected CFG element at front of block");
702  } else {
703  llvm_unreachable("Unexpected ProgramPoint");
704  }
705 
706  return PathDiagnosticLocation(S, SMng, P.getLocationContext());
707 }
708 
709 static const LocationContext *
712  const LocationContext *ParentLC = LC->getParent();
713  assert(ParentLC && "We don't start analysis from autosynthesized code");
714  while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
715  LC = ParentLC;
716  ParentLC = LC->getParent();
717  assert(ParentLC && "We don't start analysis from autosynthesized code");
718  }
719  return LC;
720 }
721 
723  // We cannot place diagnostics on autosynthesized code.
724  // Put them onto the call site through which we jumped into autosynthesized
725  // code for the first time.
726  const LocationContext *LC = N->getLocationContext();
728  // It must be a stack frame because we only autosynthesize functions.
729  return cast<StackFrameContext>(findTopAutosynthesizedParentContext(LC))
730  ->getCallSite();
731  }
732  // Otherwise, see if the node's program point directly points to a statement.
733  ProgramPoint P = N->getLocation();
734  if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
735  return SP->getStmt();
736  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>())
737  return BE->getSrc()->getTerminator();
738  if (Optional<CallEnter> CE = P.getAs<CallEnter>())
739  return CE->getCallExpr();
740  if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>())
741  return CEE->getCalleeContext()->getCallSite();
743  return PIPP->getInitializer()->getInit();
744 
745  return nullptr;
746 }
747 
749  for (N = N->getFirstSucc(); N; N = N->getFirstSucc()) {
750  if (const Stmt *S = getStmt(N)) {
751  // Check if the statement is '?' or '&&'/'||'. These are "merges",
752  // not actual statement points.
753  switch (S->getStmtClass()) {
754  case Stmt::ChooseExprClass:
755  case Stmt::BinaryConditionalOperatorClass:
756  case Stmt::ConditionalOperatorClass:
757  continue;
758  case Stmt::BinaryOperatorClass: {
759  BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
760  if (Op == BO_LAnd || Op == BO_LOr)
761  continue;
762  break;
763  }
764  default:
765  break;
766  }
767  // We found the statement, so return it.
768  return S;
769  }
770  }
771 
772  return nullptr;
773 }
774 
777  const SourceManager &SM) {
778  assert(N && "Cannot create a location with a null node.");
779  const Stmt *S = getStmt(N);
780 
781  if (!S) {
782  // If this is an implicit call, return the implicit call point location.
784  return PathDiagnosticLocation(PIE->getLocation(), SM);
785  S = getNextStmt(N);
786  }
787 
788  if (S) {
789  ProgramPoint P = N->getLocation();
790  const LocationContext *LC = N->getLocationContext();
791 
792  // For member expressions, return the location of the '.' or '->'.
793  if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
795 
796  // For binary operators, return the location of the operator.
797  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
799 
801  return PathDiagnosticLocation::createEnd(S, SM, LC);
802 
803  if (S->getLocStart().isValid())
804  return PathDiagnosticLocation(S, SM, LC);
806  }
807 
808  return createDeclEnd(N->getLocationContext(), SM);
809 }
810 
812  const PathDiagnosticLocation &PDL) {
813  FullSourceLoc L = PDL.asLocation();
814  return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
815 }
816 
818  PathDiagnosticLocation::genLocation(SourceLocation L,
819  LocationOrAnalysisDeclContext LAC) const {
820  assert(isValid());
821  // Note that we want a 'switch' here so that the compiler can warn us in
822  // case we add more cases.
823  switch (K) {
824  case SingleLocK:
825  case RangeK:
826  break;
827  case StmtK:
828  // Defensive checking.
829  if (!S)
830  break;
831  return FullSourceLoc(getValidSourceLocation(S, LAC),
832  const_cast<SourceManager&>(*SM));
833  case DeclK:
834  // Defensive checking.
835  if (!D)
836  break;
837  return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
838  }
839 
840  return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
841 }
842 
844  PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
845  assert(isValid());
846  // Note that we want a 'switch' here so that the compiler can warn us in
847  // case we add more cases.
848  switch (K) {
849  case SingleLocK:
850  return PathDiagnosticRange(SourceRange(Loc,Loc), true);
851  case RangeK:
852  break;
853  case StmtK: {
854  const Stmt *S = asStmt();
855  switch (S->getStmtClass()) {
856  default:
857  break;
858  case Stmt::DeclStmtClass: {
859  const DeclStmt *DS = cast<DeclStmt>(S);
860  if (DS->isSingleDecl()) {
861  // Should always be the case, but we'll be defensive.
862  return SourceRange(DS->getLocStart(),
863  DS->getSingleDecl()->getLocation());
864  }
865  break;
866  }
867  // FIXME: Provide better range information for different
868  // terminators.
869  case Stmt::IfStmtClass:
870  case Stmt::WhileStmtClass:
871  case Stmt::DoStmtClass:
872  case Stmt::ForStmtClass:
873  case Stmt::ChooseExprClass:
874  case Stmt::IndirectGotoStmtClass:
875  case Stmt::SwitchStmtClass:
876  case Stmt::BinaryConditionalOperatorClass:
877  case Stmt::ConditionalOperatorClass:
878  case Stmt::ObjCForCollectionStmtClass: {
880  return SourceRange(L, L);
881  }
882  }
883  SourceRange R = S->getSourceRange();
884  if (R.isValid())
885  return R;
886  break;
887  }
888  case DeclK:
889  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
890  return MD->getSourceRange();
891  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
892  if (Stmt *Body = FD->getBody())
893  return Body->getSourceRange();
894  }
895  else {
896  SourceLocation L = D->getLocation();
897  return PathDiagnosticRange(SourceRange(L, L), true);
898  }
899  }
900 
901  return SourceRange(Loc,Loc);
902 }
903 
905  if (K == StmtK) {
906  K = RangeK;
907  S = nullptr;
908  D = nullptr;
909  }
910  else if (K == DeclK) {
911  K = SingleLocK;
912  S = nullptr;
913  D = nullptr;
914  }
915 }
916 
917 //===----------------------------------------------------------------------===//
918 // Manipulation of PathDiagnosticCallPieces.
919 //===----------------------------------------------------------------------===//
920 
921 std::shared_ptr<PathDiagnosticCallPiece>
923  const SourceManager &SM) {
924  const Decl *caller = CE.getLocationContext()->getDecl();
926  CE.getLocationContext(),
927  SM);
928  return std::shared_ptr<PathDiagnosticCallPiece>(
929  new PathDiagnosticCallPiece(caller, pos));
930 }
931 
934  const Decl *caller) {
935  std::shared_ptr<PathDiagnosticCallPiece> C(
936  new PathDiagnosticCallPiece(path, caller));
937  path.clear();
938  auto *R = C.get();
939  path.push_front(std::move(C));
940  return R;
941 }
942 
944  const SourceManager &SM) {
945  const StackFrameContext *CalleeCtx = CE.getCalleeContext();
946  Callee = CalleeCtx->getDecl();
947 
948  callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
949  callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
950 
951  // Autosynthesized property accessors are special because we'd never
952  // pop back up to non-autosynthesized code until we leave them.
953  // This is not generally true for autosynthesized callees, which may call
954  // non-autosynthesized callbacks.
955  // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
956  // defaults to false.
957  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Callee))
958  IsCalleeAnAutosynthesizedPropertyAccessor = (
959  MD->isPropertyAccessor() &&
961 }
962 
963 static inline void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
964  StringRef Prefix = StringRef()) {
965  if (!D->getIdentifier())
966  return;
967  Out << Prefix << '\'' << *D << '\'';
968 }
969 
970 static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
971  bool ExtendedDescription,
972  StringRef Prefix = StringRef()) {
973  if (!D)
974  return false;
975 
976  if (isa<BlockDecl>(D)) {
977  if (ExtendedDescription)
978  Out << Prefix << "anonymous block";
979  return ExtendedDescription;
980  }
981 
982  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
983  Out << Prefix;
984  if (ExtendedDescription && !MD->isUserProvided()) {
985  if (MD->isExplicitlyDefaulted())
986  Out << "defaulted ";
987  else
988  Out << "implicit ";
989  }
990 
991  if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(MD)) {
992  if (CD->isDefaultConstructor())
993  Out << "default ";
994  else if (CD->isCopyConstructor())
995  Out << "copy ";
996  else if (CD->isMoveConstructor())
997  Out << "move ";
998 
999  Out << "constructor";
1000  describeClass(Out, MD->getParent(), " for ");
1001 
1002  } else if (isa<CXXDestructorDecl>(MD)) {
1003  if (!MD->isUserProvided()) {
1004  Out << "destructor";
1005  describeClass(Out, MD->getParent(), " for ");
1006  } else {
1007  // Use ~Foo for explicitly-written destructors.
1008  Out << "'" << *MD << "'";
1009  }
1010 
1011  } else if (MD->isCopyAssignmentOperator()) {
1012  Out << "copy assignment operator";
1013  describeClass(Out, MD->getParent(), " for ");
1014 
1015  } else if (MD->isMoveAssignmentOperator()) {
1016  Out << "move assignment operator";
1017  describeClass(Out, MD->getParent(), " for ");
1018 
1019  } else {
1020  if (MD->getParent()->getIdentifier())
1021  Out << "'" << *MD->getParent() << "::" << *MD << "'";
1022  else
1023  Out << "'" << *MD << "'";
1024  }
1025 
1026  return true;
1027  }
1028 
1029  Out << Prefix << '\'' << cast<NamedDecl>(*D) << '\'';
1030  return true;
1031 }
1032 
1033 std::shared_ptr<PathDiagnosticEventPiece>
1035  // We do not produce call enters and call exits for autosynthesized property
1036  // accessors. We do generally produce them for other functions coming from
1037  // the body farm because they may call callbacks that bring us back into
1038  // visible code.
1039  if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
1040  return nullptr;
1041 
1042  SmallString<256> buf;
1043  llvm::raw_svector_ostream Out(buf);
1044 
1045  Out << "Calling ";
1046  describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
1047 
1048  assert(callEnter.asLocation().isValid());
1049  return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
1050 }
1051 
1052 std::shared_ptr<PathDiagnosticEventPiece>
1054  if (!callEnterWithin.asLocation().isValid())
1055  return nullptr;
1056  if (Callee->isImplicit() || !Callee->hasBody())
1057  return nullptr;
1058  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee))
1059  if (MD->isDefaulted())
1060  return nullptr;
1061 
1062  SmallString<256> buf;
1063  llvm::raw_svector_ostream Out(buf);
1064 
1065  Out << "Entered call";
1066  describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
1067 
1068  return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
1069 }
1070 
1071 std::shared_ptr<PathDiagnosticEventPiece>
1073  // We do not produce call enters and call exits for autosynthesized property
1074  // accessors. We do generally produce them for other functions coming from
1075  // the body farm because they may call callbacks that bring us back into
1076  // visible code.
1077  if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
1078  return nullptr;
1079 
1080  SmallString<256> buf;
1081  llvm::raw_svector_ostream Out(buf);
1082 
1083  if (!CallStackMessage.empty()) {
1084  Out << CallStackMessage;
1085  } else {
1086  bool DidDescribe = describeCodeDecl(Out, Callee,
1087  /*ExtendedDescription=*/false,
1088  "Returning from ");
1089  if (!DidDescribe)
1090  Out << "Returning to caller";
1091  }
1092 
1093  assert(callReturn.asLocation().isValid());
1094  return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
1095 }
1096 
1097 static void compute_path_size(const PathPieces &pieces, unsigned &size) {
1098  for (PathPieces::const_iterator it = pieces.begin(),
1099  et = pieces.end(); it != et; ++it) {
1100  const PathDiagnosticPiece *piece = it->get();
1101  if (const PathDiagnosticCallPiece *cp =
1102  dyn_cast<PathDiagnosticCallPiece>(piece)) {
1103  compute_path_size(cp->path, size);
1104  }
1105  else
1106  ++size;
1107  }
1108 }
1109 
1111  unsigned size = 0;
1112  compute_path_size(path, size);
1113  return size;
1114 }
1115 
1116 //===----------------------------------------------------------------------===//
1117 // FoldingSet profiling methods.
1118 //===----------------------------------------------------------------------===//
1119 
1120 void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
1121  ID.AddInteger(Range.getBegin().getRawEncoding());
1122  ID.AddInteger(Range.getEnd().getRawEncoding());
1123  ID.AddInteger(Loc.getRawEncoding());
1124 }
1125 
1126 void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1127  ID.AddInteger((unsigned) getKind());
1128  ID.AddString(str);
1129  // FIXME: Add profiling support for code hints.
1130  ID.AddInteger((unsigned) getDisplayHint());
1131  ArrayRef<SourceRange> Ranges = getRanges();
1132  for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
1133  I != E; ++I) {
1134  ID.AddInteger(I->getBegin().getRawEncoding());
1135  ID.AddInteger(I->getEnd().getRawEncoding());
1136  }
1137 }
1138 
1139 void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1141  for (PathPieces::const_iterator it = path.begin(),
1142  et = path.end(); it != et; ++it) {
1143  ID.Add(**it);
1144  }
1145 }
1146 
1147 void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1149  ID.Add(Pos);
1150 }
1151 
1152 void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1154  for (const_iterator I = begin(), E = end(); I != E; ++I)
1155  ID.Add(*I);
1156 }
1157 
1158 void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1160  for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end();
1161  I != E; ++I)
1162  ID.Add(**I);
1163 }
1164 
1165 void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
1167 }
1168 
1169 void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
1170  ID.Add(getLocation());
1171  ID.AddString(BugType);
1172  ID.AddString(VerboseDesc);
1173  ID.AddString(Category);
1174 }
1175 
1176 void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1177  Profile(ID);
1178  for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E; ++I)
1179  ID.Add(**I);
1180  for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1181  ID.AddString(*I);
1182 }
1183 
1185 
1187  ProgramPoint P = N->getLocation();
1188  CallExitEnd CExit = P.castAs<CallExitEnd>();
1189 
1190  // FIXME: Use CallEvent to abstract this over all calls.
1191  const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
1192  const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite);
1193  if (!CE)
1194  return "";
1195 
1196  if (!N)
1197  return getMessageForSymbolNotFound();
1198 
1199  // Check if one of the parameters are set to the interesting symbol.
1201  const LocationContext *LCtx = N->getLocationContext();
1202  unsigned ArgIndex = 0;
1203  for (CallExpr::const_arg_iterator I = CE->arg_begin(),
1204  E = CE->arg_end(); I != E; ++I, ++ArgIndex){
1205  SVal SV = State->getSVal(*I, LCtx);
1206 
1207  // Check if the variable corresponding to the symbol is passed by value.
1208  SymbolRef AS = SV.getAsLocSymbol();
1209  if (AS == Sym) {
1210  return getMessageForArg(*I, ArgIndex);
1211  }
1212 
1213  // Check if the parameter is a pointer to the symbol.
1215  SVal PSV = State->getSVal(Reg->getRegion());
1216  SymbolRef AS = PSV.getAsLocSymbol();
1217  if (AS == Sym) {
1218  return getMessageForArg(*I, ArgIndex);
1219  }
1220  }
1221  }
1222 
1223  // Check if we are returning the interesting symbol.
1224  SVal SV = State->getSVal(CE, LCtx);
1225  SymbolRef RetSym = SV.getAsLocSymbol();
1226  if (RetSym == Sym) {
1227  return getMessageForReturn(CE);
1228  }
1229 
1230  return getMessageForSymbolNotFound();
1231 }
1232 
1234  unsigned ArgIndex) {
1235  // Printed parameters start at 1, not 0.
1236  ++ArgIndex;
1237 
1238  SmallString<200> buf;
1239  llvm::raw_svector_ostream os(buf);
1240 
1241  os << Msg << " via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1242  << " parameter";
1243 
1244  return os.str();
1245 }
SourceLocation getRBracLoc() const
Definition: Stmt.h:678
CFGNewAllocator - Represents C++ allocator call.
Definition: CFG.h:158
An instance of this class is created to represent a function declaration or definition.
Definition: Decl.h:1697
Expr * getInit() const
Get the initializer.
Definition: DeclCXX.h:2367
static Optional< bool > compareMacro(const PathDiagnosticMacroPiece &X, const PathDiagnosticMacroPiece &Y)
const Stmt * getStmt() const
Definition: CFG.h:122
Stmt * getBody() const
Get the body of the Declaration.
static void compute_path_size(const PathPieces &pieces, unsigned &size)
std::deque< std::string >::const_iterator meta_iterator
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:974
FullSourceLoc getExpansionLoc() const
Stmt - This represents one statement.
Definition: Stmt.h:66
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:585
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:279
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:552
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type...
Definition: CFG.h:90
SourceLocation getLocEnd() const LLVM_READONLY
Definition: DeclBase.h:412
const ProgramStateRef & getState() const
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:2397
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:74
SourceLocation getColonLoc() const
Definition: Expr.h:3259
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:139
meta_iterator meta_begin() const
const Stmt * getTriggerStmt() const
Definition: CFG.h:263
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:29
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
Definition: Decl.h:265
DeclarationName getDeclName() const
getDeclName - Get the actual, stored name of the declaration, which may be a special name...
Definition: Decl.h:291
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:253
StringRef getVerboseDescription() const
static const LocationContext * findTopAutosynthesizedParentContext(const LocationContext *LC)
int Category
Definition: Format.cpp:1348
Optional< T > getLocationAs() const LLVM_LVALUE_FUNCTION
bool isInvalid() const
static PathDiagnosticCallPiece * getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP, const SourceManager &SMgr)
BinaryOperatorKind
std::vector< PathDiagnosticLocationPair >::const_iterator const_iterator
SourceLocation getLBracLoc() const
Definition: Stmt.h:677
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:2985
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:458
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)
arg_iterator arg_end()
Definition: Expr.h:2309
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:143
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:3269
Const iterator for iterating over Stmt * arrays that contain only Expr *.
Definition: Stmt.h:346
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:595
const Stmt * getCallSite() const
SourceLocation getLocEnd() const LLVM_READONLY
Definition: Stmt.cpp:290
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
CFGBlock - Represents a single basic block in a source-level CFG.
Definition: CFG.h:422
PDFileEntry::ConsumerFiles * getFiles(const PathDiagnostic &PD)
Represents a point when we finish the call exit sequence (for inlined call).
Definition: ProgramPoint.h:639
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:4898
static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y)
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.
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
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:2587
const SourceManager & SM
Definition: Format.cpp:1337
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
StringRef getCategory() const
static Optional< bool > comparePiece(const PathDiagnosticPiece &X, const PathDiagnosticPiece &Y)
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
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:408
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:110
std::shared_ptr< PathDiagnosticEventPiece > getCallEnterEvent() const
#define false
Definition: stdbool.h:33
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:3023
std::shared_ptr< PathDiagnosticEventPiece > getCallExitEvent() const
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type...
Definition: ProgramPoint.h:140
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:487
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:1964
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:63
static PathDiagnosticLocation createEnd(const Stmt *S, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)
Create a location for the end of the statement.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
const Decl * getDecl() const
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
Definition: CFG.h:101
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.
SourceLocation getLocStart() const LLVM_READONLY
Definition: Stmt.h:516
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:569
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:595
void FlushDiagnostics(FilesMade *FilesMade)
BinaryOperator::Opcode getOpcode(const SymExpr *SE)
const StackFrameContext * getCalleeContext() const
Definition: ProgramPoint.h:646
const ExplodedNode * getFirstSucc() const
StmtClass getStmtClass() const
Definition: Stmt.h:378
const Decl * getSingleDecl() const
Definition: Stmt.h:504
static Optional< bool > compareCall(const PathDiagnosticCallPiece &X, const PathDiagnosticCallPiece &Y)
void Profile(llvm::FoldingSetNodeID &ID) const override
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl. ...
Definition: Stmt.h:500
const Decl * getDecl() const
const CXXDeleteExpr * getDeleteExpr() const
Definition: CFG.h:289
bool isMacroID() const
void appendToDesc(StringRef S)
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
arg_iterator arg_begin()
Definition: Expr.h:2308
const LocationContext * getLocationContext() const
Definition: ProgramPoint.h:179
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:13010
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:2387
Represents a C++ struct/union/class.
Definition: DeclCXX.h:299
bool isValid() const
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
Create a location corresponding to the next valid ExplodedNode as end of path location.
CFGElement - Represents a top-level expression in a basic block.
Definition: CFG.h:54
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:265
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2209
A SourceLocation and its associated SourceManager.
PathDiagnosticLocation callEnterWithin
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:915
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:138
A trivial tuple used to represent a source range.
NamedDecl - This represents a decl with a name.
Definition: Decl.h:245
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:151
AnalysisDeclContext * getAnalysisDeclContext() const
SourceLocation getLocStart() const LLVM_READONLY
Definition: Stmt.cpp:277
SourceLocation getBegin() const
static Optional< bool > compareControlFlow(const PathDiagnosticControlFlowPiece &X, const PathDiagnosticControlFlowPiece &Y)
This class handles loading and caching of source files into memory.
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
Definition: DeclBase.cpp:869
SourceLocation getLocation() const
Definition: DeclBase.h:416
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.