clang  3.8.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 (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end();
33  I!=E; ++I) {
34  if (isa<PathDiagnosticEventPiece>(*I))
35  return true;
36  if (PathDiagnosticMacroPiece *MP = dyn_cast<PathDiagnosticMacroPiece>(*I))
37  if (MP->containsEvent())
38  return true;
39  }
40  return false;
41 }
42 
43 static StringRef StripTrailingDots(StringRef s) {
44  for (StringRef::size_type i = s.size(); i != 0; --i)
45  if (s[i - 1] != '.')
46  return s.substr(0, i);
47  return "";
48 }
49 
50 PathDiagnosticPiece::PathDiagnosticPiece(StringRef s,
51  Kind k, DisplayHint hint)
52  : str(StripTrailingDots(s)), kind(k), Hint(hint),
53  LastInMainSourceFile(false) {}
54 
55 PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
56  : kind(k), Hint(hint), LastInMainSourceFile(false) {}
57 
63 
64 
65 void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
66  bool ShouldFlattenMacros) const {
67  for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
68  PathDiagnosticPiece *Piece = I->get();
69 
70  switch (Piece->getKind()) {
72  PathDiagnosticCallPiece *Call = cast<PathDiagnosticCallPiece>(Piece);
74  Call->getCallEnterEvent();
75  if (CallEnter)
76  Current.push_back(CallEnter);
77  Call->path.flattenTo(Primary, Primary, ShouldFlattenMacros);
79  Call->getCallExitEvent();
80  if (callExit)
81  Current.push_back(callExit);
82  break;
83  }
85  PathDiagnosticMacroPiece *Macro = cast<PathDiagnosticMacroPiece>(Piece);
86  if (ShouldFlattenMacros) {
87  Macro->subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
88  } else {
89  Current.push_back(Piece);
90  PathPieces NewPath;
91  Macro->subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
92  // FIXME: This probably shouldn't mutate the original path piece.
93  Macro->subPieces = NewPath;
94  }
95  break;
96  }
99  Current.push_back(Piece);
100  break;
101  }
102  }
103 }
104 
105 
107 
108 PathDiagnostic::PathDiagnostic(StringRef CheckName, const Decl *declWithIssue,
109  StringRef bugtype, StringRef verboseDesc,
110  StringRef shortDesc, StringRef category,
111  PathDiagnosticLocation LocationToUnique,
112  const Decl *DeclToUnique)
113  : CheckName(CheckName),
114  DeclWithIssue(declWithIssue),
115  BugType(StripTrailingDots(bugtype)),
116  VerboseDesc(StripTrailingDots(verboseDesc)),
117  ShortDesc(StripTrailingDots(shortDesc)),
118  Category(StripTrailingDots(category)),
119  UniqueingLoc(LocationToUnique),
120  UniqueingDecl(DeclToUnique),
121  path(pathImpl) {}
122 
125  const SourceManager &SMgr) {
126  SourceLocation CallLoc = CP->callEnter.asLocation();
127 
128  // If the call is within a macro, don't do anything (for now).
129  if (CallLoc.isMacroID())
130  return nullptr;
131 
132  assert(SMgr.isInMainFile(CallLoc) &&
133  "The call piece should be in the main file.");
134 
135  // Check if CP represents a path through a function outside of the main file.
136  if (!SMgr.isInMainFile(CP->callEnterWithin.asLocation()))
137  return CP;
138 
139  const PathPieces &Path = CP->path;
140  if (Path.empty())
141  return nullptr;
142 
143  // Check if the last piece in the callee path is a call to a function outside
144  // of the main file.
145  if (PathDiagnosticCallPiece *CPInner =
146  dyn_cast<PathDiagnosticCallPiece>(Path.back())) {
147  return getFirstStackedCallToHeaderFile(CPInner, SMgr);
148  }
149 
150  // Otherwise, the last piece is in the main file.
151  return nullptr;
152 }
153 
155  if (path.empty())
156  return;
157 
158  PathDiagnosticPiece *LastP = path.back().get();
159  assert(LastP);
160  const SourceManager &SMgr = LastP->getLocation().getManager();
161 
162  // We only need to check if the report ends inside headers, if the last piece
163  // is a call piece.
164  if (PathDiagnosticCallPiece *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
165  CP = getFirstStackedCallToHeaderFile(CP, SMgr);
166  if (CP) {
167  // Mark the piece.
168  CP->setAsLastInMainSourceFile();
169 
170  // Update the path diagnostic message.
171  const NamedDecl *ND = dyn_cast<NamedDecl>(CP->getCallee());
172  if (ND) {
173  SmallString<200> buf;
174  llvm::raw_svector_ostream os(buf);
175  os << " (within a call to '" << ND->getDeclName() << "')";
176  appendToDesc(os.str());
177  }
178 
179  // Reset the report containing declaration and location.
180  DeclWithIssue = CP->getCaller();
181  Loc = CP->getLocation();
182 
183  return;
184  }
185  }
186 }
187 
188 void PathDiagnosticConsumer::anchor() { }
189 
191  // Delete the contents of the FoldingSet if it isn't empty already.
193  Diags.begin(), et = Diags.end() ; it != et ; ++it) {
194  delete &*it;
195  }
196 }
197 
199  std::unique_ptr<PathDiagnostic> D) {
200  if (!D || D->path.empty())
201  return;
202 
203  // We need to flatten the locations (convert Stmt* to locations) because
204  // the referenced statements may be freed by the time the diagnostics
205  // are emitted.
206  D->flattenLocations();
207 
208  // If the PathDiagnosticConsumer does not support diagnostics that
209  // cross file boundaries, prune out such diagnostics now.
211  // Verify that the entire path is from the same FileID.
212  FileID FID;
213  const SourceManager &SMgr = D->path.front()->getLocation().getManager();
215  WorkList.push_back(&D->path);
216 
217  while (!WorkList.empty()) {
218  const PathPieces &path = *WorkList.pop_back_val();
219 
220  for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E;
221  ++I) {
222  const PathDiagnosticPiece *piece = I->get();
224 
225  if (FID.isInvalid()) {
226  FID = SMgr.getFileID(L);
227  } else if (SMgr.getFileID(L) != FID)
228  return; // FIXME: Emit a warning?
229 
230  // Check the source ranges.
232  for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
233  E = Ranges.end(); I != E; ++I) {
234  SourceLocation L = SMgr.getExpansionLoc(I->getBegin());
235  if (!L.isFileID() || SMgr.getFileID(L) != FID)
236  return; // FIXME: Emit a warning?
237  L = SMgr.getExpansionLoc(I->getEnd());
238  if (!L.isFileID() || SMgr.getFileID(L) != FID)
239  return; // FIXME: Emit a warning?
240  }
241 
242  if (const PathDiagnosticCallPiece *call =
243  dyn_cast<PathDiagnosticCallPiece>(piece)) {
244  WorkList.push_back(&call->path);
245  }
246  else if (const PathDiagnosticMacroPiece *macro =
247  dyn_cast<PathDiagnosticMacroPiece>(piece)) {
248  WorkList.push_back(&macro->subPieces);
249  }
250  }
251  }
252 
253  if (FID.isInvalid())
254  return; // FIXME: Emit a warning?
255  }
256 
257  // Profile the node to see if we already have something matching it
258  llvm::FoldingSetNodeID profile;
259  D->Profile(profile);
260  void *InsertPos = nullptr;
261 
262  if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
263  // Keep the PathDiagnostic with the shorter path.
264  // Note, the enclosing routine is called in deterministic order, so the
265  // results will be consistent between runs (no reason to break ties if the
266  // size is the same).
267  const unsigned orig_size = orig->full_size();
268  const unsigned new_size = D->full_size();
269  if (orig_size <= new_size)
270  return;
271 
272  assert(orig != D.get());
273  Diags.RemoveNode(orig);
274  delete orig;
275  }
276 
277  Diags.InsertNode(D.release());
278 }
279 
280 static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y);
281 static Optional<bool>
286  if (XSL != YSL)
287  return XSL.isBeforeInTranslationUnitThan(YSL);
290  if (XEL != YEL)
291  return XEL.isBeforeInTranslationUnitThan(YEL);
292  return None;
293 }
294 
296  const PathDiagnosticMacroPiece &Y) {
297  return comparePath(X.subPieces, Y.subPieces);
298 }
299 
301  const PathDiagnosticCallPiece &Y) {
302  FullSourceLoc X_CEL = X.callEnter.asLocation();
303  FullSourceLoc Y_CEL = Y.callEnter.asLocation();
304  if (X_CEL != Y_CEL)
305  return X_CEL.isBeforeInTranslationUnitThan(Y_CEL);
308  if (X_CEWL != Y_CEWL)
309  return X_CEWL.isBeforeInTranslationUnitThan(Y_CEWL);
310  FullSourceLoc X_CRL = X.callReturn.asLocation();
311  FullSourceLoc Y_CRL = Y.callReturn.asLocation();
312  if (X_CRL != Y_CRL)
313  return X_CRL.isBeforeInTranslationUnitThan(Y_CRL);
314  return comparePath(X.path, Y.path);
315 }
316 
318  const PathDiagnosticPiece &Y) {
319  if (X.getKind() != Y.getKind())
320  return X.getKind() < Y.getKind();
321 
324  if (XL != YL)
325  return XL.isBeforeInTranslationUnitThan(YL);
326 
327  if (X.getString() != Y.getString())
328  return X.getString() < Y.getString();
329 
330  if (X.getRanges().size() != Y.getRanges().size())
331  return X.getRanges().size() < Y.getRanges().size();
332 
333  const SourceManager &SM = XL.getManager();
334 
335  for (unsigned i = 0, n = X.getRanges().size(); i < n; ++i) {
336  SourceRange XR = X.getRanges()[i];
337  SourceRange YR = Y.getRanges()[i];
338  if (XR != YR) {
339  if (XR.getBegin() != YR.getBegin())
340  return SM.isBeforeInTranslationUnit(XR.getBegin(), YR.getBegin());
341  return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd());
342  }
343  }
344 
345  switch (X.getKind()) {
347  return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X),
348  cast<PathDiagnosticControlFlowPiece>(Y));
350  return None;
352  return compareMacro(cast<PathDiagnosticMacroPiece>(X),
353  cast<PathDiagnosticMacroPiece>(Y));
355  return compareCall(cast<PathDiagnosticCallPiece>(X),
356  cast<PathDiagnosticCallPiece>(Y));
357  }
358  llvm_unreachable("all cases handled");
359 }
360 
362  if (X.size() != Y.size())
363  return X.size() < Y.size();
364 
365  PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
366  PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
367 
368  for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) {
369  Optional<bool> b = comparePiece(**X_I, **Y_I);
370  if (b.hasValue())
371  return b.getValue();
372  }
373 
374  return None;
375 }
376 
377 static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
380  if (XL != YL)
381  return XL.isBeforeInTranslationUnitThan(YL);
382  if (X.getBugType() != Y.getBugType())
383  return X.getBugType() < Y.getBugType();
384  if (X.getCategory() != Y.getCategory())
385  return X.getCategory() < Y.getCategory();
389  return X.getShortDescription() < Y.getShortDescription();
390  if (X.getDeclWithIssue() != Y.getDeclWithIssue()) {
391  const Decl *XD = X.getDeclWithIssue();
392  if (!XD)
393  return true;
394  const Decl *YD = Y.getDeclWithIssue();
395  if (!YD)
396  return false;
397  SourceLocation XDL = XD->getLocation();
398  SourceLocation YDL = YD->getLocation();
399  if (XDL != YDL) {
400  const SourceManager &SM = XL.getManager();
401  return SM.isBeforeInTranslationUnit(XDL, YDL);
402  }
403  }
406  if (XE - XI != YE - YI)
407  return (XE - XI) < (YE - YI);
408  for ( ; XI != XE ; ++XI, ++YI) {
409  if (*XI != *YI)
410  return (*XI) < (*YI);
411  }
413  assert(b.hasValue());
414  return b.getValue();
415 }
416 
419  if (flushed)
420  return;
421 
422  flushed = true;
423 
424  std::vector<const PathDiagnostic *> BatchDiags;
426  et = Diags.end(); it != et; ++it) {
427  const PathDiagnostic *D = &*it;
428  BatchDiags.push_back(D);
429  }
430 
431  // Sort the diagnostics so that they are always emitted in a deterministic
432  // order.
433  int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
434  [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
435  assert(*X != *Y && "PathDiagnostics not uniqued!");
436  if (compare(**X, **Y))
437  return -1;
438  assert(compare(**Y, **X) && "Not a total order!");
439  return 1;
440  };
441  array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
442 
443  FlushDiagnosticsImpl(BatchDiags, Files);
444 
445  // Delete the flushed diagnostics.
446  for (std::vector<const PathDiagnostic *>::iterator it = BatchDiags.begin(),
447  et = BatchDiags.end(); it != et; ++it) {
448  const PathDiagnostic *D = *it;
449  delete D;
450  }
451 
452  // Clear out the FoldingSet.
453  Diags.clear();
454 }
455 
457  for (PDFileEntry &Entry : Set)
458  Entry.~PDFileEntry();
459 }
460 
462  StringRef ConsumerName,
463  StringRef FileName) {
464  llvm::FoldingSetNodeID NodeID;
465  NodeID.Add(PD);
466  void *InsertPos;
467  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
468  if (!Entry) {
469  Entry = Alloc.Allocate<PDFileEntry>();
470  Entry = new (Entry) PDFileEntry(NodeID);
471  Set.InsertNode(Entry, InsertPos);
472  }
473 
474  // Allocate persistent storage for the file name.
475  char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
476  memcpy(FileName_cstr, FileName.data(), FileName.size());
477 
478  Entry->files.push_back(std::make_pair(ConsumerName,
479  StringRef(FileName_cstr,
480  FileName.size())));
481 }
482 
485  llvm::FoldingSetNodeID NodeID;
486  NodeID.Add(PD);
487  void *InsertPos;
488  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
489  if (!Entry)
490  return nullptr;
491  return &Entry->files;
492 }
493 
494 //===----------------------------------------------------------------------===//
495 // PathDiagnosticLocation methods.
496 //===----------------------------------------------------------------------===//
497 
500  bool UseEnd = false) {
501  SourceLocation L = UseEnd ? S->getLocEnd() : S->getLocStart();
502  assert(!LAC.isNull() && "A valid LocationContext or AnalysisDeclContext should "
503  "be passed to PathDiagnosticLocation upon creation.");
504 
505  // S might be a temporary statement that does not have a location in the
506  // source code, so find an enclosing statement and use its location.
507  if (!L.isValid()) {
508 
509  AnalysisDeclContext *ADC;
510  if (LAC.is<const LocationContext*>())
511  ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext();
512  else
513  ADC = LAC.get<AnalysisDeclContext*>();
514 
515  ParentMap &PM = ADC->getParentMap();
516 
517  const Stmt *Parent = S;
518  do {
519  Parent = PM.getParent(Parent);
520 
521  // In rare cases, we have implicit top-level expressions,
522  // such as arguments for implicit member initializers.
523  // In this case, fall back to the start of the body (even if we were
524  // asked for the statement end location).
525  if (!Parent) {
526  const Stmt *Body = ADC->getBody();
527  if (Body)
528  L = Body->getLocStart();
529  else
530  L = ADC->getDecl()->getLocEnd();
531  break;
532  }
533 
534  L = UseEnd ? Parent->getLocEnd() : Parent->getLocStart();
535  } while (!L.isValid());
536  }
537 
538  return L;
539 }
540 
543  const LocationContext *CallerCtx,
544  const SourceManager &SM) {
545  const CFGBlock &Block = *SFC->getCallSiteBlock();
546  CFGElement Source = Block[SFC->getIndex()];
547 
548  switch (Source.getKind()) {
550  return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
551  SM, CallerCtx);
553  const CFGInitializer &Init = Source.castAs<CFGInitializer>();
555  SM, CallerCtx);
556  }
558  const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
560  SM, CallerCtx);
561  }
562  case CFGElement::DeleteDtor: {
563  const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
564  return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
565  }
567  case CFGElement::MemberDtor: {
568  const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
569  if (const Stmt *CallerBody = CallerInfo->getBody())
570  return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
571  return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
572  }
575  llvm_unreachable("not yet implemented!");
576  }
577 
578  llvm_unreachable("Unknown CFGElement kind");
579 }
580 
581 
584  const SourceManager &SM) {
585  return PathDiagnosticLocation(D->getLocStart(), SM, SingleLocK);
586 }
587 
590  const SourceManager &SM,
593  SM, SingleLocK);
594 }
595 
596 
599  const SourceManager &SM,
601  if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(S))
602  return createEndBrace(CS, SM);
603  return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
604  SM, SingleLocK);
605 }
606 
609  const SourceManager &SM) {
610  return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
611 }
612 
615  const ConditionalOperator *CO,
616  const SourceManager &SM) {
617  return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
618 }
619 
620 
623  const SourceManager &SM) {
624  return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
625 }
626 
629  const SourceManager &SM) {
630  SourceLocation L = CS->getLBracLoc();
631  return PathDiagnosticLocation(L, SM, SingleLocK);
632 }
633 
636  const SourceManager &SM) {
637  SourceLocation L = CS->getRBracLoc();
638  return PathDiagnosticLocation(L, SM, SingleLocK);
639 }
640 
643  const SourceManager &SM) {
644  // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
645  if (const CompoundStmt *CS =
646  dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
647  if (!CS->body_empty()) {
648  SourceLocation Loc = (*CS->body_begin())->getLocStart();
649  return PathDiagnosticLocation(Loc, SM, SingleLocK);
650  }
651 
652  return PathDiagnosticLocation();
653 }
654 
657  const SourceManager &SM) {
658  SourceLocation L = LC->getDecl()->getBodyRBrace();
659  return PathDiagnosticLocation(L, SM, SingleLocK);
660 }
661 
664  const SourceManager &SMng) {
665 
666  const Stmt* S = nullptr;
667  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
668  const CFGBlock *BSrc = BE->getSrc();
669  S = BSrc->getTerminatorCondition();
670  } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
671  S = SP->getStmt();
674  } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
675  return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
676  SMng);
677  } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
678  return PathDiagnosticLocation(PIE->getLocation(), SMng);
679  } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
680  return getLocationForCaller(CE->getCalleeContext(),
681  CE->getLocationContext(),
682  SMng);
683  } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
684  return getLocationForCaller(CEE->getCalleeContext(),
685  CEE->getLocationContext(),
686  SMng);
687  } else {
688  llvm_unreachable("Unexpected ProgramPoint");
689  }
690 
691  return PathDiagnosticLocation(S, SMng, P.getLocationContext());
692 }
693 
695  ProgramPoint P = N->getLocation();
696  if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
697  return SP->getStmt();
698  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>())
699  return BE->getSrc()->getTerminator();
700  if (Optional<CallEnter> CE = P.getAs<CallEnter>())
701  return CE->getCallExpr();
702  if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>())
703  return CEE->getCalleeContext()->getCallSite();
705  return PIPP->getInitializer()->getInit();
706 
707  return nullptr;
708 }
709 
711  for (N = N->getFirstSucc(); N; N = N->getFirstSucc()) {
712  if (const Stmt *S = getStmt(N)) {
713  // Check if the statement is '?' or '&&'/'||'. These are "merges",
714  // not actual statement points.
715  switch (S->getStmtClass()) {
716  case Stmt::ChooseExprClass:
717  case Stmt::BinaryConditionalOperatorClass:
718  case Stmt::ConditionalOperatorClass:
719  continue;
720  case Stmt::BinaryOperatorClass: {
721  BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
722  if (Op == BO_LAnd || Op == BO_LOr)
723  continue;
724  break;
725  }
726  default:
727  break;
728  }
729  // We found the statement, so return it.
730  return S;
731  }
732  }
733 
734  return nullptr;
735 }
736 
739  const SourceManager &SM) {
740  assert(N && "Cannot create a location with a null node.");
741  const Stmt *S = getStmt(N);
742 
743  if (!S) {
744  // If this is an implicit call, return the implicit call point location.
746  return PathDiagnosticLocation(PIE->getLocation(), SM);
747  S = getNextStmt(N);
748  }
749 
750  if (S) {
751  ProgramPoint P = N->getLocation();
752  const LocationContext *LC = N->getLocationContext();
753 
754  // For member expressions, return the location of the '.' or '->'.
755  if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
757 
758  // For binary operators, return the location of the operator.
759  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
761 
763  return PathDiagnosticLocation::createEnd(S, SM, LC);
764 
765  if (S->getLocStart().isValid())
766  return PathDiagnosticLocation(S, SM, LC);
768  }
769 
770  return createDeclEnd(N->getLocationContext(), SM);
771 }
772 
774  const PathDiagnosticLocation &PDL) {
775  FullSourceLoc L = PDL.asLocation();
776  return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
777 }
778 
780  PathDiagnosticLocation::genLocation(SourceLocation L,
781  LocationOrAnalysisDeclContext LAC) const {
782  assert(isValid());
783  // Note that we want a 'switch' here so that the compiler can warn us in
784  // case we add more cases.
785  switch (K) {
786  case SingleLocK:
787  case RangeK:
788  break;
789  case StmtK:
790  // Defensive checking.
791  if (!S)
792  break;
794  const_cast<SourceManager&>(*SM));
795  case DeclK:
796  // Defensive checking.
797  if (!D)
798  break;
799  return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
800  }
801 
802  return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
803 }
804 
806  PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
807  assert(isValid());
808  // Note that we want a 'switch' here so that the compiler can warn us in
809  // case we add more cases.
810  switch (K) {
811  case SingleLocK:
812  return PathDiagnosticRange(SourceRange(Loc,Loc), true);
813  case RangeK:
814  break;
815  case StmtK: {
816  const Stmt *S = asStmt();
817  switch (S->getStmtClass()) {
818  default:
819  break;
820  case Stmt::DeclStmtClass: {
821  const DeclStmt *DS = cast<DeclStmt>(S);
822  if (DS->isSingleDecl()) {
823  // Should always be the case, but we'll be defensive.
824  return SourceRange(DS->getLocStart(),
825  DS->getSingleDecl()->getLocation());
826  }
827  break;
828  }
829  // FIXME: Provide better range information for different
830  // terminators.
831  case Stmt::IfStmtClass:
832  case Stmt::WhileStmtClass:
833  case Stmt::DoStmtClass:
834  case Stmt::ForStmtClass:
835  case Stmt::ChooseExprClass:
836  case Stmt::IndirectGotoStmtClass:
837  case Stmt::SwitchStmtClass:
838  case Stmt::BinaryConditionalOperatorClass:
839  case Stmt::ConditionalOperatorClass:
840  case Stmt::ObjCForCollectionStmtClass: {
842  return SourceRange(L, L);
843  }
844  }
845  SourceRange R = S->getSourceRange();
846  if (R.isValid())
847  return R;
848  break;
849  }
850  case DeclK:
851  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
852  return MD->getSourceRange();
853  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
854  if (Stmt *Body = FD->getBody())
855  return Body->getSourceRange();
856  }
857  else {
858  SourceLocation L = D->getLocation();
859  return PathDiagnosticRange(SourceRange(L, L), true);
860  }
861  }
862 
863  return SourceRange(Loc,Loc);
864 }
865 
867  if (K == StmtK) {
868  K = RangeK;
869  S = nullptr;
870  D = nullptr;
871  }
872  else if (K == DeclK) {
873  K = SingleLocK;
874  S = nullptr;
875  D = nullptr;
876  }
877 }
878 
879 //===----------------------------------------------------------------------===//
880 // Manipulation of PathDiagnosticCallPieces.
881 //===----------------------------------------------------------------------===//
882 
885  const CallExitEnd &CE,
886  const SourceManager &SM) {
887  const Decl *caller = CE.getLocationContext()->getDecl();
889  CE.getLocationContext(),
890  SM);
891  return new PathDiagnosticCallPiece(caller, pos);
892 }
893 
896  const Decl *caller) {
898  path.clear();
899  path.push_front(C);
900  return C;
901 }
902 
903 void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
904  const SourceManager &SM) {
905  const StackFrameContext *CalleeCtx = CE.getCalleeContext();
906  Callee = CalleeCtx->getDecl();
907 
908  callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
909  callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
910 }
911 
912 static inline void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
913  StringRef Prefix = StringRef()) {
914  if (!D->getIdentifier())
915  return;
916  Out << Prefix << '\'' << *D << '\'';
917 }
918 
919 static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
920  bool ExtendedDescription,
921  StringRef Prefix = StringRef()) {
922  if (!D)
923  return false;
924 
925  if (isa<BlockDecl>(D)) {
926  if (ExtendedDescription)
927  Out << Prefix << "anonymous block";
928  return ExtendedDescription;
929  }
930 
931  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
932  Out << Prefix;
933  if (ExtendedDescription && !MD->isUserProvided()) {
934  if (MD->isExplicitlyDefaulted())
935  Out << "defaulted ";
936  else
937  Out << "implicit ";
938  }
939 
940  if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(MD)) {
941  if (CD->isDefaultConstructor())
942  Out << "default ";
943  else if (CD->isCopyConstructor())
944  Out << "copy ";
945  else if (CD->isMoveConstructor())
946  Out << "move ";
947 
948  Out << "constructor";
949  describeClass(Out, MD->getParent(), " for ");
950 
951  } else if (isa<CXXDestructorDecl>(MD)) {
952  if (!MD->isUserProvided()) {
953  Out << "destructor";
954  describeClass(Out, MD->getParent(), " for ");
955  } else {
956  // Use ~Foo for explicitly-written destructors.
957  Out << "'" << *MD << "'";
958  }
959 
960  } else if (MD->isCopyAssignmentOperator()) {
961  Out << "copy assignment operator";
962  describeClass(Out, MD->getParent(), " for ");
963 
964  } else if (MD->isMoveAssignmentOperator()) {
965  Out << "move assignment operator";
966  describeClass(Out, MD->getParent(), " for ");
967 
968  } else {
969  if (MD->getParent()->getIdentifier())
970  Out << "'" << *MD->getParent() << "::" << *MD << "'";
971  else
972  Out << "'" << *MD << "'";
973  }
974 
975  return true;
976  }
977 
978  Out << Prefix << '\'' << cast<NamedDecl>(*D) << '\'';
979  return true;
980 }
981 
984  if (!Callee)
985  return nullptr;
986 
987  SmallString<256> buf;
988  llvm::raw_svector_ostream Out(buf);
989 
990  Out << "Calling ";
991  describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
992 
993  assert(callEnter.asLocation().isValid());
994  return new PathDiagnosticEventPiece(callEnter, Out.str());
995 }
996 
999  if (!callEnterWithin.asLocation().isValid())
1000  return nullptr;
1001  if (Callee->isImplicit() || !Callee->hasBody())
1002  return nullptr;
1003  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee))
1004  if (MD->isDefaulted())
1005  return nullptr;
1006 
1007  SmallString<256> buf;
1008  llvm::raw_svector_ostream Out(buf);
1009 
1010  Out << "Entered call";
1011  describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
1012 
1013  return new PathDiagnosticEventPiece(callEnterWithin, Out.str());
1014 }
1015 
1018  if (NoExit)
1019  return nullptr;
1020 
1021  SmallString<256> buf;
1022  llvm::raw_svector_ostream Out(buf);
1023 
1024  if (!CallStackMessage.empty()) {
1025  Out << CallStackMessage;
1026  } else {
1027  bool DidDescribe = describeCodeDecl(Out, Callee,
1028  /*ExtendedDescription=*/false,
1029  "Returning from ");
1030  if (!DidDescribe)
1031  Out << "Returning to caller";
1032  }
1033 
1034  assert(callReturn.asLocation().isValid());
1035  return new PathDiagnosticEventPiece(callReturn, Out.str());
1036 }
1037 
1038 static void compute_path_size(const PathPieces &pieces, unsigned &size) {
1039  for (PathPieces::const_iterator it = pieces.begin(),
1040  et = pieces.end(); it != et; ++it) {
1041  const PathDiagnosticPiece *piece = it->get();
1042  if (const PathDiagnosticCallPiece *cp =
1043  dyn_cast<PathDiagnosticCallPiece>(piece)) {
1044  compute_path_size(cp->path, size);
1045  }
1046  else
1047  ++size;
1048  }
1049 }
1050 
1052  unsigned size = 0;
1053  compute_path_size(path, size);
1054  return size;
1055 }
1056 
1057 //===----------------------------------------------------------------------===//
1058 // FoldingSet profiling methods.
1059 //===----------------------------------------------------------------------===//
1060 
1061 void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
1062  ID.AddInteger(Range.getBegin().getRawEncoding());
1063  ID.AddInteger(Range.getEnd().getRawEncoding());
1064  ID.AddInteger(Loc.getRawEncoding());
1065  return;
1066 }
1067 
1068 void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1069  ID.AddInteger((unsigned) getKind());
1070  ID.AddString(str);
1071  // FIXME: Add profiling support for code hints.
1072  ID.AddInteger((unsigned) getDisplayHint());
1073  ArrayRef<SourceRange> Ranges = getRanges();
1074  for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
1075  I != E; ++I) {
1076  ID.AddInteger(I->getBegin().getRawEncoding());
1077  ID.AddInteger(I->getEnd().getRawEncoding());
1078  }
1079 }
1080 
1081 void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1083  for (PathPieces::const_iterator it = path.begin(),
1084  et = path.end(); it != et; ++it) {
1085  ID.Add(**it);
1086  }
1087 }
1088 
1089 void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1091  ID.Add(Pos);
1092 }
1093 
1094 void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1096  for (const_iterator I = begin(), E = end(); I != E; ++I)
1097  ID.Add(*I);
1098 }
1099 
1100 void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1102  for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end();
1103  I != E; ++I)
1104  ID.Add(**I);
1105 }
1106 
1107 void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
1108  ID.Add(getLocation());
1109  ID.AddString(BugType);
1110  ID.AddString(VerboseDesc);
1111  ID.AddString(Category);
1112 }
1113 
1114 void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1115  Profile(ID);
1116  for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E; ++I)
1117  ID.Add(**I);
1118  for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1119  ID.AddString(*I);
1120 }
1121 
1123 
1125  ProgramPoint P = N->getLocation();
1126  CallExitEnd CExit = P.castAs<CallExitEnd>();
1127 
1128  // FIXME: Use CallEvent to abstract this over all calls.
1129  const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
1130  const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite);
1131  if (!CE)
1132  return "";
1133 
1134  if (!N)
1135  return getMessageForSymbolNotFound();
1136 
1137  // Check if one of the parameters are set to the interesting symbol.
1139  const LocationContext *LCtx = N->getLocationContext();
1140  unsigned ArgIndex = 0;
1142  E = CE->arg_end(); I != E; ++I, ++ArgIndex){
1143  SVal SV = State->getSVal(*I, LCtx);
1144 
1145  // Check if the variable corresponding to the symbol is passed by value.
1146  SymbolRef AS = SV.getAsLocSymbol();
1147  if (AS == Sym) {
1148  return getMessageForArg(*I, ArgIndex);
1149  }
1150 
1151  // Check if the parameter is a pointer to the symbol.
1153  SVal PSV = State->getSVal(Reg->getRegion());
1154  SymbolRef AS = PSV.getAsLocSymbol();
1155  if (AS == Sym) {
1156  return getMessageForArg(*I, ArgIndex);
1157  }
1158  }
1159  }
1160 
1161  // Check if we are returning the interesting symbol.
1162  SVal SV = State->getSVal(CE, LCtx);
1163  SymbolRef RetSym = SV.getAsLocSymbol();
1164  if (RetSym == Sym) {
1165  return getMessageForReturn(CE);
1166  }
1167 
1168  return getMessageForSymbolNotFound();
1169 }
1170 
1172  unsigned ArgIndex) {
1173  // Printed parameters start at 1, not 0.
1174  ++ArgIndex;
1175 
1176  SmallString<200> buf;
1177  llvm::raw_svector_ostream os(buf);
1178 
1179  os << Msg << " via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1180  << " parameter";
1181 
1182  return os.str();
1183 }
SourceLocation getEnd() const
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Definition: Decl.h:1483
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:164
std::deque< std::string >::const_iterator meta_iterator
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:77
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
const SourceManager & getManager() const
CFGDeleteDtor - Represents C++ object destructor generated from a call to delete. ...
Definition: CFG.h:218
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:228
SourceLocation getOperatorLoc() const
Definition: Expr.h:2915
SourceLocation getLocEnd() const LLVM_READONLY
Definition: DeclBase.h:380
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2134
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:2119
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:113
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.
iterator begin() const
Definition: Type.h:4072
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: SymbolManager.h:42
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
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:194
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:69
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type...
Definition: CFG.h:87
int Category
Definition: Format.cpp:1726
SourceLocation getLBracLoc() const
Definition: Stmt.h:617
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
SmallVector< CharSourceRange, 8 > Ranges
Definition: Format.cpp:1715
std::vector< PathDiagnosticLocationPair >::const_iterator const_iterator
unsigned getIndex() const
IntrusiveRefCntPtr< PathDiagnosticEventPiece > getCallExitEvent() const
const CFGBlock * getCallSiteBlock() const
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:2875
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 PathDiagnosticCallPiece * construct(const ExplodedNode *N, const CallExitEnd &CE, const SourceManager &SM)
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
iterator end() const
detail::InMemoryDirectory::const_iterator I
virtual PathDiagnosticLocation getLocation() const =0
const Stmt * getTriggerStmt() const
Definition: CFG.h:204
static SourceLocation getValidSourceLocation(const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEnd=false)
arg_iterator arg_end()
Definition: Expr.h:2230
const LocationContext * getLocationContext() const
static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME, const SourceManager &SM)
For member expressions, return the location of the '.
AnnotatingParser & P
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:3148
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:539
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
CFGBlock - Represents a single basic block in a source-level CFG.
Definition: CFG.h:353
PDFileEntry::ConsumerFiles * getFiles(const PathDiagnostic &PD)
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
Definition: DeclBase.cpp:726
Stmt * getBody() const
Get the body of the Declaration.
IntrusiveRefCntPtr< PathDiagnosticEventPiece > getCallEnterWithinCallerEvent() const
Represents a point when we finish the call exit sequence (for inlined call).
Definition: ProgramPoint.h:631
ID
Defines the set of possible language-specific address spaces.
Definition: AddressSpaces.h:27
SourceManager & SM
Expr - This represents one expression.
Definition: Expr.h:104
const ProgramStateRef & getState() const
void FullProfile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, including its path.
Stmt * getTerminatorCondition(bool StripParens=true)
Definition: CFG.cpp:4537
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:138
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:86
const ExplodedNode * getFirstSucc() const
PathDiagnosticLocation getEndLocation() const
IntrusiveRefCntPtr< PathDiagnosticEventPiece > getCallEnterEvent() 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:190
virtual bool supportsCrossFileDiagnostics() const
Return true if the PathDiagnosticConsumer supports individual PathDiagnostics that span multiple file...
PathDiagnosticLocation getStartLocation() const
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:377
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
virtual void FlushDiagnosticsImpl(std::vector< const PathDiagnostic * > &Diags, FilesMade *filesMade)=0
ConstExprIterator const_arg_iterator
Definition: Expr.h:2220
Encodes a location in the source.
const TemplateArgument * iterator
Definition: Type.h:4070
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:445
bool isValid() const
void Profile(llvm::FoldingSetNodeID &ID) const
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Definition: Stmt.h:431
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:1701
const Stmt * getStmt() const
Definition: CFG.h:119
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:44
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:860
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)
Definition: Type.h:4095
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:638
const Decl * getDecl() const
SourceLocation getBegin() const
const Decl * getSingleDecl() const
Definition: Stmt.h:449
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
ConsumerFiles files
A vector of <consumer,file> pairs.
SourceLocation getLocStart() const LLVM_READONLY
Definition: Stmt.h:461
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)
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:2493
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:2229
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:11761
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:2297
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:285
Kind getKind() const
Definition: CFG.h:107
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:53
static StringRef StripTrailingDots(StringRef s)
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Definition: DiagnosticIDs.h:43
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2134
A SourceLocation and its associated SourceManager.
PathDiagnosticLocation callEnterWithin
SourceLocation getRBracLoc() const
Definition: Stmt.h:618
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:772
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:133
A trivial tuple used to represent a source range.
SourceLocation getLocation() const
Definition: DeclBase.h:384
NamedDecl - This represents a decl with a name.
Definition: Decl.h:145
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
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:3138
unsigned full_size()
Return the unrolled size of the path.
void Profile(llvm::FoldingSetNodeID &ID) const override