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