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