clang  9.0.0svn
PathDiagnostic.cpp
Go to the documentation of this file.
1 //===- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the PathDiagnostic-related interfaces.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "clang/AST/Decl.h"
15 #include "clang/AST/DeclBase.h"
16 #include "clang/AST/DeclCXX.h"
17 #include "clang/AST/DeclObjC.h"
18 #include "clang/AST/DeclTemplate.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/ExprCXX.h"
22 #include "clang/AST/ParentMap.h"
23 #include "clang/AST/Stmt.h"
24 #include "clang/AST/Type.h"
26 #include "clang/Analysis/CFG.h"
29 #include "clang/Basic/LLVM.h"
35 #include "llvm/ADT/ArrayRef.h"
36 #include "llvm/ADT/FoldingSet.h"
37 #include "llvm/ADT/None.h"
38 #include "llvm/ADT/Optional.h"
39 #include "llvm/ADT/STLExtras.h"
40 #include "llvm/ADT/SmallString.h"
41 #include "llvm/ADT/SmallVector.h"
42 #include "llvm/ADT/StringExtras.h"
43 #include "llvm/ADT/StringRef.h"
44 #include "llvm/Support/Casting.h"
45 #include "llvm/Support/ErrorHandling.h"
46 #include "llvm/Support/raw_ostream.h"
47 #include <cassert>
48 #include <cstring>
49 #include <memory>
50 #include <utility>
51 #include <vector>
52 
53 using namespace clang;
54 using namespace ento;
55 
57  for (const auto &P : subPieces) {
58  if (isa<PathDiagnosticEventPiece>(*P))
59  return true;
60  if (const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(P.get()))
61  if (MP->containsEvent())
62  return true;
63  }
64  return false;
65 }
66 
67 static StringRef StripTrailingDots(StringRef s) {
68  for (StringRef::size_type i = s.size(); i != 0; --i)
69  if (s[i - 1] != '.')
70  return s.substr(0, i);
71  return {};
72 }
73 
75  Kind k, DisplayHint hint)
76  : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
77 
79  : kind(k), Hint(hint) {}
80 
82 
84 
86 
88 
90 
92 
94 
95 void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
96  bool ShouldFlattenMacros) const {
97  for (auto &Piece : *this) {
98  switch (Piece->getKind()) {
100  auto &Call = cast<PathDiagnosticCallPiece>(*Piece);
101  if (auto CallEnter = Call.getCallEnterEvent())
102  Current.push_back(std::move(CallEnter));
103  Call.path.flattenTo(Primary, Primary, ShouldFlattenMacros);
104  if (auto callExit = Call.getCallExitEvent())
105  Current.push_back(std::move(callExit));
106  break;
107  }
109  auto &Macro = cast<PathDiagnosticMacroPiece>(*Piece);
110  if (ShouldFlattenMacros) {
111  Macro.subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
112  } else {
113  Current.push_back(Piece);
114  PathPieces NewPath;
115  Macro.subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
116  // FIXME: This probably shouldn't mutate the original path piece.
117  Macro.subPieces = NewPath;
118  }
119  break;
120  }
125  Current.push_back(Piece);
126  break;
127  }
128  }
129 }
130 
132 
134  StringRef CheckName, const Decl *declWithIssue, StringRef bugtype,
135  StringRef verboseDesc, StringRef shortDesc, StringRef category,
136  PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique,
137  std::unique_ptr<FilesToLineNumsMap> ExecutedLines)
138  : CheckName(CheckName), DeclWithIssue(declWithIssue),
139  BugType(StripTrailingDots(bugtype)),
140  VerboseDesc(StripTrailingDots(verboseDesc)),
141  ShortDesc(StripTrailingDots(shortDesc)),
142  Category(StripTrailingDots(category)), UniqueingLoc(LocationToUnique),
143  UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)),
144  path(pathImpl) {}
145 
146 static PathDiagnosticCallPiece *
147 getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP,
148  const SourceManager &SMgr) {
149  SourceLocation CallLoc = CP->callEnter.asLocation();
150 
151  // If the call is within a macro, don't do anything (for now).
152  if (CallLoc.isMacroID())
153  return nullptr;
154 
155  assert(AnalysisManager::isInCodeFile(CallLoc, SMgr) &&
156  "The call piece should not be in a header file.");
157 
158  // Check if CP represents a path through a function outside of the main file.
159  if (!AnalysisManager::isInCodeFile(CP->callEnterWithin.asLocation(), SMgr))
160  return CP;
161 
162  const PathPieces &Path = CP->path;
163  if (Path.empty())
164  return nullptr;
165 
166  // Check if the last piece in the callee path is a call to a function outside
167  // of the main file.
168  if (auto *CPInner = dyn_cast<PathDiagnosticCallPiece>(Path.back().get()))
169  return getFirstStackedCallToHeaderFile(CPInner, SMgr);
170 
171  // Otherwise, the last piece is in the main file.
172  return nullptr;
173 }
174 
176  if (path.empty())
177  return;
178 
179  PathDiagnosticPiece *LastP = path.back().get();
180  assert(LastP);
181  const SourceManager &SMgr = LastP->getLocation().getManager();
182 
183  // We only need to check if the report ends inside headers, if the last piece
184  // is a call piece.
185  if (auto *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
186  CP = getFirstStackedCallToHeaderFile(CP, SMgr);
187  if (CP) {
188  // Mark the piece.
189  CP->setAsLastInMainSourceFile();
190 
191  // Update the path diagnostic message.
192  const auto *ND = dyn_cast<NamedDecl>(CP->getCallee());
193  if (ND) {
194  SmallString<200> buf;
195  llvm::raw_svector_ostream os(buf);
196  os << " (within a call to '" << ND->getDeclName() << "')";
197  appendToDesc(os.str());
198  }
199 
200  // Reset the report containing declaration and location.
201  DeclWithIssue = CP->getCaller();
202  Loc = CP->getLocation();
203 
204  return;
205  }
206  }
207 }
208 
209 void PathDiagnosticConsumer::anchor() {}
210 
212  // Delete the contents of the FoldingSet if it isn't empty already.
213  for (auto &Diag : Diags)
214  delete &Diag;
215 }
216 
218  std::unique_ptr<PathDiagnostic> D) {
219  if (!D || D->path.empty())
220  return;
221 
222  // We need to flatten the locations (convert Stmt* to locations) because
223  // the referenced statements may be freed by the time the diagnostics
224  // are emitted.
225  D->flattenLocations();
226 
227  // If the PathDiagnosticConsumer does not support diagnostics that
228  // cross file boundaries, prune out such diagnostics now.
229  if (!supportsCrossFileDiagnostics()) {
230  // Verify that the entire path is from the same FileID.
231  FileID FID;
232  const SourceManager &SMgr = D->path.front()->getLocation().getManager();
234  WorkList.push_back(&D->path);
235  SmallString<128> buf;
236  llvm::raw_svector_ostream warning(buf);
237  warning << "warning: Path diagnostic report is not generated. Current "
238  << "output format does not support diagnostics that cross file "
239  << "boundaries. Refer to --analyzer-output for valid output "
240  << "formats\n";
241 
242  while (!WorkList.empty()) {
243  const PathPieces &path = *WorkList.pop_back_val();
244 
245  for (const auto &I : path) {
246  const PathDiagnosticPiece *piece = I.get();
248 
249  if (FID.isInvalid()) {
250  FID = SMgr.getFileID(L);
251  } else if (SMgr.getFileID(L) != FID) {
252  llvm::errs() << warning.str();
253  return;
254  }
255 
256  // Check the source ranges.
257  ArrayRef<SourceRange> Ranges = piece->getRanges();
258  for (const auto &I : Ranges) {
259  SourceLocation L = SMgr.getExpansionLoc(I.getBegin());
260  if (!L.isFileID() || SMgr.getFileID(L) != FID) {
261  llvm::errs() << warning.str();
262  return;
263  }
264  L = SMgr.getExpansionLoc(I.getEnd());
265  if (!L.isFileID() || SMgr.getFileID(L) != FID) {
266  llvm::errs() << warning.str();
267  return;
268  }
269  }
270 
271  if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece))
272  WorkList.push_back(&call->path);
273  else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece))
274  WorkList.push_back(&macro->subPieces);
275  }
276  }
277 
278  if (FID.isInvalid())
279  return; // FIXME: Emit a warning?
280  }
281 
282  // Profile the node to see if we already have something matching it
283  llvm::FoldingSetNodeID profile;
284  D->Profile(profile);
285  void *InsertPos = nullptr;
286 
287  if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
288  // Keep the PathDiagnostic with the shorter path.
289  // Note, the enclosing routine is called in deterministic order, so the
290  // results will be consistent between runs (no reason to break ties if the
291  // size is the same).
292  const unsigned orig_size = orig->full_size();
293  const unsigned new_size = D->full_size();
294  if (orig_size <= new_size)
295  return;
296 
297  assert(orig != D.get());
298  Diags.RemoveNode(orig);
299  delete orig;
300  }
301 
302  Diags.InsertNode(D.release());
303 }
304 
305 static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y);
306 
307 static Optional<bool>
308 compareControlFlow(const PathDiagnosticControlFlowPiece &X,
309  const PathDiagnosticControlFlowPiece &Y) {
310  FullSourceLoc XSL = X.getStartLocation().asLocation();
311  FullSourceLoc YSL = Y.getStartLocation().asLocation();
312  if (XSL != YSL)
313  return XSL.isBeforeInTranslationUnitThan(YSL);
314  FullSourceLoc XEL = X.getEndLocation().asLocation();
315  FullSourceLoc YEL = Y.getEndLocation().asLocation();
316  if (XEL != YEL)
317  return XEL.isBeforeInTranslationUnitThan(YEL);
318  return None;
319 }
320 
322  const PathDiagnosticMacroPiece &Y) {
323  return comparePath(X.subPieces, Y.subPieces);
324 }
325 
326 static Optional<bool> compareCall(const PathDiagnosticCallPiece &X,
327  const PathDiagnosticCallPiece &Y) {
328  FullSourceLoc X_CEL = X.callEnter.asLocation();
329  FullSourceLoc Y_CEL = Y.callEnter.asLocation();
330  if (X_CEL != Y_CEL)
331  return X_CEL.isBeforeInTranslationUnitThan(Y_CEL);
332  FullSourceLoc X_CEWL = X.callEnterWithin.asLocation();
333  FullSourceLoc Y_CEWL = Y.callEnterWithin.asLocation();
334  if (X_CEWL != Y_CEWL)
335  return X_CEWL.isBeforeInTranslationUnitThan(Y_CEWL);
336  FullSourceLoc X_CRL = X.callReturn.asLocation();
337  FullSourceLoc Y_CRL = Y.callReturn.asLocation();
338  if (X_CRL != Y_CRL)
339  return X_CRL.isBeforeInTranslationUnitThan(Y_CRL);
340  return comparePath(X.path, Y.path);
341 }
342 
344  const PathDiagnosticPiece &Y) {
345  if (X.getKind() != Y.getKind())
346  return X.getKind() < Y.getKind();
347 
348  FullSourceLoc XL = X.getLocation().asLocation();
349  FullSourceLoc YL = Y.getLocation().asLocation();
350  if (XL != YL)
351  return XL.isBeforeInTranslationUnitThan(YL);
352 
353  if (X.getString() != Y.getString())
354  return X.getString() < Y.getString();
355 
356  if (X.getRanges().size() != Y.getRanges().size())
357  return X.getRanges().size() < Y.getRanges().size();
358 
359  const SourceManager &SM = XL.getManager();
360 
361  for (unsigned i = 0, n = X.getRanges().size(); i < n; ++i) {
362  SourceRange XR = X.getRanges()[i];
363  SourceRange YR = Y.getRanges()[i];
364  if (XR != YR) {
365  if (XR.getBegin() != YR.getBegin())
366  return SM.isBeforeInTranslationUnit(XR.getBegin(), YR.getBegin());
367  return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd());
368  }
369  }
370 
371  switch (X.getKind()) {
373  return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X),
374  cast<PathDiagnosticControlFlowPiece>(Y));
376  return compareMacro(cast<PathDiagnosticMacroPiece>(X),
377  cast<PathDiagnosticMacroPiece>(Y));
379  return compareCall(cast<PathDiagnosticCallPiece>(X),
380  cast<PathDiagnosticCallPiece>(Y));
384  return None;
385  }
386  llvm_unreachable("all cases handled");
387 }
388 
389 static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) {
390  if (X.size() != Y.size())
391  return X.size() < Y.size();
392 
393  PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
394  PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
395 
396  for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) {
397  Optional<bool> b = comparePiece(**X_I, **Y_I);
398  if (b.hasValue())
399  return b.getValue();
400  }
401 
402  return None;
403 }
404 
406  std::pair<FileID, unsigned> XOffs = XL.getDecomposedLoc();
407  std::pair<FileID, unsigned> YOffs = YL.getDecomposedLoc();
408  const SourceManager &SM = XL.getManager();
409  std::pair<bool, bool> InSameTU = SM.isInTheSameTranslationUnit(XOffs, YOffs);
410  if (InSameTU.first)
411  return XL.isBeforeInTranslationUnitThan(YL);
412  const FileEntry *XFE = SM.getFileEntryForID(XL.getSpellingLoc().getFileID());
413  const FileEntry *YFE = SM.getFileEntryForID(YL.getSpellingLoc().getFileID());
414  if (!XFE || !YFE)
415  return XFE && !YFE;
416  int NameCmp = XFE->getName().compare(YFE->getName());
417  if (NameCmp != 0)
418  return NameCmp == -1;
419  // Last resort: Compare raw file IDs that are possibly expansions.
420  return XL.getFileID() < YL.getFileID();
421 }
422 
423 static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
424  FullSourceLoc XL = X.getLocation().asLocation();
425  FullSourceLoc YL = Y.getLocation().asLocation();
426  if (XL != YL)
427  return compareCrossTUSourceLocs(XL, YL);
428  if (X.getBugType() != Y.getBugType())
429  return X.getBugType() < Y.getBugType();
430  if (X.getCategory() != Y.getCategory())
431  return X.getCategory() < Y.getCategory();
432  if (X.getVerboseDescription() != Y.getVerboseDescription())
433  return X.getVerboseDescription() < Y.getVerboseDescription();
434  if (X.getShortDescription() != Y.getShortDescription())
435  return X.getShortDescription() < Y.getShortDescription();
436  if (X.getDeclWithIssue() != Y.getDeclWithIssue()) {
437  const Decl *XD = X.getDeclWithIssue();
438  if (!XD)
439  return true;
440  const Decl *YD = Y.getDeclWithIssue();
441  if (!YD)
442  return false;
443  SourceLocation XDL = XD->getLocation();
444  SourceLocation YDL = YD->getLocation();
445  if (XDL != YDL) {
446  const SourceManager &SM = XL.getManager();
447  return compareCrossTUSourceLocs(FullSourceLoc(XDL, SM),
448  FullSourceLoc(YDL, SM));
449  }
450  }
451  PathDiagnostic::meta_iterator XI = X.meta_begin(), XE = X.meta_end();
452  PathDiagnostic::meta_iterator YI = Y.meta_begin(), YE = Y.meta_end();
453  if (XE - XI != YE - YI)
454  return (XE - XI) < (YE - YI);
455  for ( ; XI != XE ; ++XI, ++YI) {
456  if (*XI != *YI)
457  return (*XI) < (*YI);
458  }
459  Optional<bool> b = comparePath(X.path, Y.path);
460  assert(b.hasValue());
461  return b.getValue();
462 }
463 
466  if (flushed)
467  return;
468 
469  flushed = true;
470 
471  std::vector<const PathDiagnostic *> BatchDiags;
472  for (const auto &D : Diags)
473  BatchDiags.push_back(&D);
474 
475  // Sort the diagnostics so that they are always emitted in a deterministic
476  // order.
477  int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
478  [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
479  assert(*X != *Y && "PathDiagnostics not uniqued!");
480  if (compare(**X, **Y))
481  return -1;
482  assert(compare(**Y, **X) && "Not a total order!");
483  return 1;
484  };
485  array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
486 
487  FlushDiagnosticsImpl(BatchDiags, Files);
488 
489  // Delete the flushed diagnostics.
490  for (const auto D : BatchDiags)
491  delete D;
492 
493  // Clear out the FoldingSet.
494  Diags.clear();
495 }
496 
498  for (PDFileEntry &Entry : Set)
499  Entry.~PDFileEntry();
500 }
501 
503  StringRef ConsumerName,
504  StringRef FileName) {
505  llvm::FoldingSetNodeID NodeID;
506  NodeID.Add(PD);
507  void *InsertPos;
508  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
509  if (!Entry) {
510  Entry = Alloc.Allocate<PDFileEntry>();
511  Entry = new (Entry) PDFileEntry(NodeID);
512  Set.InsertNode(Entry, InsertPos);
513  }
514 
515  // Allocate persistent storage for the file name.
516  char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
517  memcpy(FileName_cstr, FileName.data(), FileName.size());
518 
519  Entry->files.push_back(std::make_pair(ConsumerName,
520  StringRef(FileName_cstr,
521  FileName.size())));
522 }
523 
526  llvm::FoldingSetNodeID NodeID;
527  NodeID.Add(PD);
528  void *InsertPos;
529  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
530  if (!Entry)
531  return nullptr;
532  return &Entry->files;
533 }
534 
535 //===----------------------------------------------------------------------===//
536 // PathDiagnosticLocation methods.
537 //===----------------------------------------------------------------------===//
538 
541  bool UseEnd = false) {
542  SourceLocation L = UseEnd ? S->getEndLoc() : S->getBeginLoc();
543  assert(!LAC.isNull() && "A valid LocationContext or AnalysisDeclContext should "
544  "be passed to PathDiagnosticLocation upon creation.");
545 
546  // S might be a temporary statement that does not have a location in the
547  // source code, so find an enclosing statement and use its location.
548  if (!L.isValid()) {
549  AnalysisDeclContext *ADC;
550  if (LAC.is<const LocationContext*>())
551  ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext();
552  else
553  ADC = LAC.get<AnalysisDeclContext*>();
554 
555  ParentMap &PM = ADC->getParentMap();
556 
557  const Stmt *Parent = S;
558  do {
559  Parent = PM.getParent(Parent);
560 
561  // In rare cases, we have implicit top-level expressions,
562  // such as arguments for implicit member initializers.
563  // In this case, fall back to the start of the body (even if we were
564  // asked for the statement end location).
565  if (!Parent) {
566  const Stmt *Body = ADC->getBody();
567  if (Body)
568  L = Body->getBeginLoc();
569  else
570  L = ADC->getDecl()->getEndLoc();
571  break;
572  }
573 
574  L = UseEnd ? Parent->getEndLoc() : Parent->getBeginLoc();
575  } while (!L.isValid());
576  }
577 
578  // FIXME: Ironically, this assert actually fails in some cases.
579  //assert(L.isValid());
580  return L;
581 }
582 
583 static PathDiagnosticLocation
585  const LocationContext *CallerCtx,
586  const SourceManager &SM) {
587  const CFGBlock &Block = *SFC->getCallSiteBlock();
588  CFGElement Source = Block[SFC->getIndex()];
589 
590  switch (Source.getKind()) {
594  return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
595  SM, CallerCtx);
597  const CFGInitializer &Init = Source.castAs<CFGInitializer>();
598  return PathDiagnosticLocation(Init.getInitializer()->getInit(),
599  SM, CallerCtx);
600  }
602  const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
604  SM, CallerCtx);
605  }
606  case CFGElement::DeleteDtor: {
607  const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
608  return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
609  }
611  case CFGElement::MemberDtor: {
612  const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
613  if (const Stmt *CallerBody = CallerInfo->getBody())
614  return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
615  return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
616  }
618  const CFGNewAllocator &Alloc = Source.castAs<CFGNewAllocator>();
619  return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerCtx);
620  }
622  // Temporary destructors are for temporaries. They die immediately at around
623  // the location of CXXBindTemporaryExpr. If they are lifetime-extended,
624  // they'd be dealt with via an AutomaticObjectDtor instead.
625  const auto &Dtor = Source.castAs<CFGTemporaryDtor>();
626  return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM,
627  CallerCtx);
628  }
631  llvm_unreachable("not yet implemented!");
634  llvm_unreachable("CFGElement kind should not be on callsite!");
635  }
636 
637  llvm_unreachable("Unknown CFGElement kind");
638 }
639 
640 PathDiagnosticLocation
642  const SourceManager &SM) {
643  return PathDiagnosticLocation(D->getBeginLoc(), SM, SingleLocK);
644 }
645 
648  const SourceManager &SM,
651  SM, SingleLocK);
652 }
653 
656  const SourceManager &SM,
658  if (const auto *CS = dyn_cast<CompoundStmt>(S))
659  return createEndBrace(CS, SM);
660  return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
661  SM, SingleLocK);
662 }
663 
666  const SourceManager &SM) {
667  return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
668 }
669 
672  const ConditionalOperator *CO,
673  const SourceManager &SM) {
674  return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
675 }
676 
679  const SourceManager &SM) {
680 
681  assert(ME->getMemberLoc().isValid() || ME->getBeginLoc().isValid());
682 
683  // In some cases, getMemberLoc isn't valid -- in this case we'll return with
684  // some other related valid SourceLocation.
685  if (ME->getMemberLoc().isValid())
686  return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
687 
688  return PathDiagnosticLocation(ME->getBeginLoc(), SM, SingleLocK);
689 }
690 
693  const SourceManager &SM) {
694  SourceLocation L = CS->getLBracLoc();
695  return PathDiagnosticLocation(L, SM, SingleLocK);
696 }
697 
700  const SourceManager &SM) {
701  SourceLocation L = CS->getRBracLoc();
702  return PathDiagnosticLocation(L, SM, SingleLocK);
703 }
704 
707  const SourceManager &SM) {
708  // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
709  if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
710  if (!CS->body_empty()) {
711  SourceLocation Loc = (*CS->body_begin())->getBeginLoc();
712  return PathDiagnosticLocation(Loc, SM, SingleLocK);
713  }
714 
715  return PathDiagnosticLocation();
716 }
717 
720  const SourceManager &SM) {
721  SourceLocation L = LC->getDecl()->getBodyRBrace();
722  return PathDiagnosticLocation(L, SM, SingleLocK);
723 }
724 
727  const SourceManager &SMng) {
728  const Stmt* S = nullptr;
729  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
730  const CFGBlock *BSrc = BE->getSrc();
731  if (BSrc->getTerminator().isVirtualBaseBranch()) {
732  // TODO: VirtualBaseBranches should also appear for destructors.
733  // In this case we should put the diagnostic at the end of decl.
735  P.getLocationContext()->getDecl(), SMng);
736 
737  } else {
738  S = BSrc->getTerminatorCondition();
739  if (!S) {
740  // If the BlockEdge has no terminator condition statement but its
741  // source is the entry of the CFG (e.g. a checker crated the branch at
742  // the beginning of a function), use the function's declaration instead.
743  assert(BSrc == &BSrc->getParent()->getEntry() && "CFGBlock has no "
744  "TerminatorCondition and is not the enrty block of the CFG");
746  P.getLocationContext()->getDecl(), SMng);
747  }
748  }
749  } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
750  S = SP->getStmt();
753  } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
754  return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
755  SMng);
756  } else if (Optional<PreImplicitCall> PIC = P.getAs<PreImplicitCall>()) {
757  return PathDiagnosticLocation(PIC->getLocation(), SMng);
758  } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
759  return PathDiagnosticLocation(PIE->getLocation(), SMng);
760  } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
761  return getLocationForCaller(CE->getCalleeContext(),
762  CE->getLocationContext(),
763  SMng);
764  } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
765  return getLocationForCaller(CEE->getCalleeContext(),
766  CEE->getLocationContext(),
767  SMng);
768  } else if (auto CEB = P.getAs<CallExitBegin>()) {
769  if (const ReturnStmt *RS = CEB->getReturnStmt())
770  return PathDiagnosticLocation::createBegin(RS, SMng,
771  CEB->getLocationContext());
772  return PathDiagnosticLocation(
773  CEB->getLocationContext()->getDecl()->getSourceRange().getEnd(), SMng);
774  } else if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
775  CFGElement BlockFront = BE->getBlock()->front();
776  if (auto StmtElt = BlockFront.getAs<CFGStmt>()) {
777  return PathDiagnosticLocation(StmtElt->getStmt()->getBeginLoc(), SMng);
778  } else if (auto NewAllocElt = BlockFront.getAs<CFGNewAllocator>()) {
779  return PathDiagnosticLocation(
780  NewAllocElt->getAllocatorExpr()->getBeginLoc(), SMng);
781  }
782  llvm_unreachable("Unexpected CFG element at front of block");
783  } else {
784  llvm_unreachable("Unexpected ProgramPoint");
785  }
786 
787  return PathDiagnosticLocation(S, SMng, P.getLocationContext());
788 }
789 
790 static const LocationContext *
793  const LocationContext *ParentLC = LC->getParent();
794  assert(ParentLC && "We don't start analysis from autosynthesized code");
795  while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
796  LC = ParentLC;
797  ParentLC = LC->getParent();
798  assert(ParentLC && "We don't start analysis from autosynthesized code");
799  }
800  return LC;
801 }
802 
804  // We cannot place diagnostics on autosynthesized code.
805  // Put them onto the call site through which we jumped into autosynthesized
806  // code for the first time.
807  const LocationContext *LC = N->getLocationContext();
809  // It must be a stack frame because we only autosynthesize functions.
810  return cast<StackFrameContext>(findTopAutosynthesizedParentContext(LC))
811  ->getCallSite();
812  }
813  // Otherwise, see if the node's program point directly points to a statement.
814  ProgramPoint P = N->getLocation();
815  if (auto SP = P.getAs<StmtPoint>())
816  return SP->getStmt();
817  if (auto BE = P.getAs<BlockEdge>())
818  return BE->getSrc()->getTerminatorStmt();
819  if (auto CE = P.getAs<CallEnter>())
820  return CE->getCallExpr();
821  if (auto CEE = P.getAs<CallExitEnd>())
822  return CEE->getCalleeContext()->getCallSite();
823  if (auto PIPP = P.getAs<PostInitializer>())
824  return PIPP->getInitializer()->getInit();
825  if (auto CEB = P.getAs<CallExitBegin>())
826  return CEB->getReturnStmt();
827  if (auto FEP = P.getAs<FunctionExitPoint>())
828  return FEP->getStmt();
829 
830  return nullptr;
831 }
832 
834  for (N = N->getFirstSucc(); N; N = N->getFirstSucc()) {
835  if (const Stmt *S = getStmt(N)) {
836  // Check if the statement is '?' or '&&'/'||'. These are "merges",
837  // not actual statement points.
838  switch (S->getStmtClass()) {
839  case Stmt::ChooseExprClass:
840  case Stmt::BinaryConditionalOperatorClass:
841  case Stmt::ConditionalOperatorClass:
842  continue;
843  case Stmt::BinaryOperatorClass: {
844  BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
845  if (Op == BO_LAnd || Op == BO_LOr)
846  continue;
847  break;
848  }
849  default:
850  break;
851  }
852  // We found the statement, so return it.
853  return S;
854  }
855  }
856 
857  return nullptr;
858 }
859 
862  const SourceManager &SM) {
863  assert(N && "Cannot create a location with a null node.");
864  const Stmt *S = getStmt(N);
865  const LocationContext *LC = N->getLocationContext();
866 
867  if (!S) {
868  // If this is an implicit call, return the implicit call point location.
870  return PathDiagnosticLocation(PIE->getLocation(), SM);
871  if (auto FE = N->getLocationAs<FunctionExitPoint>()) {
872  if (const ReturnStmt *RS = FE->getStmt())
873  return PathDiagnosticLocation::createBegin(RS, SM, LC);
874  }
875  S = getNextStmt(N);
876  }
877 
878  if (S) {
879  ProgramPoint P = N->getLocation();
880 
881  // For member expressions, return the location of the '.' or '->'.
882  if (const auto *ME = dyn_cast<MemberExpr>(S))
884 
885  // For binary operators, return the location of the operator.
886  if (const auto *B = dyn_cast<BinaryOperator>(S))
888 
890  return PathDiagnosticLocation::createEnd(S, SM, LC);
891 
892  if (S->getBeginLoc().isValid())
893  return PathDiagnosticLocation(S, SM, LC);
895  }
896 
897  return createDeclEnd(N->getLocationContext(), SM);
898 }
899 
901  const PathDiagnosticLocation &PDL) {
902  FullSourceLoc L = PDL.asLocation();
903  return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
904 }
905 
907  PathDiagnosticLocation::genLocation(SourceLocation L,
908  LocationOrAnalysisDeclContext LAC) const {
909  assert(isValid());
910  // Note that we want a 'switch' here so that the compiler can warn us in
911  // case we add more cases.
912  switch (K) {
913  case SingleLocK:
914  case RangeK:
915  break;
916  case StmtK:
917  // Defensive checking.
918  if (!S)
919  break;
920  return FullSourceLoc(getValidSourceLocation(S, LAC),
921  const_cast<SourceManager&>(*SM));
922  case DeclK:
923  // Defensive checking.
924  if (!D)
925  break;
926  return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
927  }
928 
929  return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
930 }
931 
933  PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
934  assert(isValid());
935  // Note that we want a 'switch' here so that the compiler can warn us in
936  // case we add more cases.
937  switch (K) {
938  case SingleLocK:
939  return PathDiagnosticRange(SourceRange(Loc,Loc), true);
940  case RangeK:
941  break;
942  case StmtK: {
943  const Stmt *S = asStmt();
944  switch (S->getStmtClass()) {
945  default:
946  break;
947  case Stmt::DeclStmtClass: {
948  const auto *DS = cast<DeclStmt>(S);
949  if (DS->isSingleDecl()) {
950  // Should always be the case, but we'll be defensive.
951  return SourceRange(DS->getBeginLoc(),
952  DS->getSingleDecl()->getLocation());
953  }
954  break;
955  }
956  // FIXME: Provide better range information for different
957  // terminators.
958  case Stmt::IfStmtClass:
959  case Stmt::WhileStmtClass:
960  case Stmt::DoStmtClass:
961  case Stmt::ForStmtClass:
962  case Stmt::ChooseExprClass:
963  case Stmt::IndirectGotoStmtClass:
964  case Stmt::SwitchStmtClass:
965  case Stmt::BinaryConditionalOperatorClass:
966  case Stmt::ConditionalOperatorClass:
967  case Stmt::ObjCForCollectionStmtClass: {
969  return SourceRange(L, L);
970  }
971  }
972  SourceRange R = S->getSourceRange();
973  if (R.isValid())
974  return R;
975  break;
976  }
977  case DeclK:
978  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
979  return MD->getSourceRange();
980  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
981  if (Stmt *Body = FD->getBody())
982  return Body->getSourceRange();
983  }
984  else {
985  SourceLocation L = D->getLocation();
986  return PathDiagnosticRange(SourceRange(L, L), true);
987  }
988  }
989 
990  return SourceRange(Loc, Loc);
991 }
992 
994  if (K == StmtK) {
995  K = RangeK;
996  S = nullptr;
997  D = nullptr;
998  }
999  else if (K == DeclK) {
1000  K = SingleLocK;
1001  S = nullptr;
1002  D = nullptr;
1003  }
1004 }
1005 
1006 //===----------------------------------------------------------------------===//
1007 // Manipulation of PathDiagnosticCallPieces.
1008 //===----------------------------------------------------------------------===//
1009 
1010 std::shared_ptr<PathDiagnosticCallPiece>
1012  const SourceManager &SM) {
1013  const Decl *caller = CE.getLocationContext()->getDecl();
1015  CE.getLocationContext(),
1016  SM);
1017  return std::shared_ptr<PathDiagnosticCallPiece>(
1018  new PathDiagnosticCallPiece(caller, pos));
1019 }
1020 
1023  const Decl *caller) {
1024  std::shared_ptr<PathDiagnosticCallPiece> C(
1025  new PathDiagnosticCallPiece(path, caller));
1026  path.clear();
1027  auto *R = C.get();
1028  path.push_front(std::move(C));
1029  return R;
1030 }
1031 
1033  const SourceManager &SM) {
1034  const StackFrameContext *CalleeCtx = CE.getCalleeContext();
1035  Callee = CalleeCtx->getDecl();
1036 
1037  callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
1038  callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
1039 
1040  // Autosynthesized property accessors are special because we'd never
1041  // pop back up to non-autosynthesized code until we leave them.
1042  // This is not generally true for autosynthesized callees, which may call
1043  // non-autosynthesized callbacks.
1044  // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
1045  // defaults to false.
1046  if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
1047  IsCalleeAnAutosynthesizedPropertyAccessor = (
1048  MD->isPropertyAccessor() &&
1050 }
1051 
1052 static void describeTemplateParameters(raw_ostream &Out,
1053  const ArrayRef<TemplateArgument> TAList,
1054  const LangOptions &LO,
1055  StringRef Prefix = StringRef(),
1056  StringRef Postfix = StringRef());
1057 
1058 static void describeTemplateParameter(raw_ostream &Out,
1059  const TemplateArgument &TArg,
1060  const LangOptions &LO) {
1061 
1062  if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
1063  describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
1064  } else {
1065  TArg.print(PrintingPolicy(LO), Out);
1066  }
1067 }
1068 
1069 static void describeTemplateParameters(raw_ostream &Out,
1070  const ArrayRef<TemplateArgument> TAList,
1071  const LangOptions &LO,
1072  StringRef Prefix, StringRef Postfix) {
1073  if (TAList.empty())
1074  return;
1075 
1076  Out << Prefix;
1077  for (int I = 0, Last = TAList.size() - 1; I != Last; ++I) {
1078  describeTemplateParameter(Out, TAList[I], LO);
1079  Out << ", ";
1080  }
1081  describeTemplateParameter(Out, TAList[TAList.size() - 1], LO);
1082  Out << Postfix;
1083 }
1084 
1085 static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
1086  StringRef Prefix = StringRef()) {
1087  if (!D->getIdentifier())
1088  return;
1089  Out << Prefix << '\'' << *D;
1090  if (const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
1091  describeTemplateParameters(Out, T->getTemplateArgs().asArray(),
1092  D->getASTContext().getLangOpts(), "<", ">");
1093 
1094  Out << '\'';
1095 }
1096 
1097 static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
1098  bool ExtendedDescription,
1099  StringRef Prefix = StringRef()) {
1100  if (!D)
1101  return false;
1102 
1103  if (isa<BlockDecl>(D)) {
1104  if (ExtendedDescription)
1105  Out << Prefix << "anonymous block";
1106  return ExtendedDescription;
1107  }
1108 
1109  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
1110  Out << Prefix;
1111  if (ExtendedDescription && !MD->isUserProvided()) {
1112  if (MD->isExplicitlyDefaulted())
1113  Out << "defaulted ";
1114  else
1115  Out << "implicit ";
1116  }
1117 
1118  if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
1119  if (CD->isDefaultConstructor())
1120  Out << "default ";
1121  else if (CD->isCopyConstructor())
1122  Out << "copy ";
1123  else if (CD->isMoveConstructor())
1124  Out << "move ";
1125 
1126  Out << "constructor";
1127  describeClass(Out, MD->getParent(), " for ");
1128  } else if (isa<CXXDestructorDecl>(MD)) {
1129  if (!MD->isUserProvided()) {
1130  Out << "destructor";
1131  describeClass(Out, MD->getParent(), " for ");
1132  } else {
1133  // Use ~Foo for explicitly-written destructors.
1134  Out << "'" << *MD << "'";
1135  }
1136  } else if (MD->isCopyAssignmentOperator()) {
1137  Out << "copy assignment operator";
1138  describeClass(Out, MD->getParent(), " for ");
1139  } else if (MD->isMoveAssignmentOperator()) {
1140  Out << "move assignment operator";
1141  describeClass(Out, MD->getParent(), " for ");
1142  } else {
1143  if (MD->getParent()->getIdentifier())
1144  Out << "'" << *MD->getParent() << "::" << *MD << "'";
1145  else
1146  Out << "'" << *MD << "'";
1147  }
1148 
1149  return true;
1150  }
1151 
1152  Out << Prefix << '\'' << cast<NamedDecl>(*D);
1153 
1154  // Adding template parameters.
1155  if (const auto FD = dyn_cast<FunctionDecl>(D))
1156  if (const TemplateArgumentList *TAList =
1157  FD->getTemplateSpecializationArgs())
1158  describeTemplateParameters(Out, TAList->asArray(),
1159  FD->getASTContext().getLangOpts(), "<", ">");
1160 
1161  Out << '\'';
1162  return true;
1163 }
1164 
1165 std::shared_ptr<PathDiagnosticEventPiece>
1167  // We do not produce call enters and call exits for autosynthesized property
1168  // accessors. We do generally produce them for other functions coming from
1169  // the body farm because they may call callbacks that bring us back into
1170  // visible code.
1171  if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
1172  return nullptr;
1173 
1174  SmallString<256> buf;
1175  llvm::raw_svector_ostream Out(buf);
1176 
1177  Out << "Calling ";
1178  describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
1179 
1180  assert(callEnter.asLocation().isValid());
1181  return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
1182 }
1183 
1184 std::shared_ptr<PathDiagnosticEventPiece>
1186  if (!callEnterWithin.asLocation().isValid())
1187  return nullptr;
1188  if (Callee->isImplicit() || !Callee->hasBody())
1189  return nullptr;
1190  if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
1191  if (MD->isDefaulted())
1192  return nullptr;
1193 
1194  SmallString<256> buf;
1195  llvm::raw_svector_ostream Out(buf);
1196 
1197  Out << "Entered call";
1198  describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
1199 
1200  return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
1201 }
1202 
1203 std::shared_ptr<PathDiagnosticEventPiece>
1205  // We do not produce call enters and call exits for autosynthesized property
1206  // accessors. We do generally produce them for other functions coming from
1207  // the body farm because they may call callbacks that bring us back into
1208  // visible code.
1209  if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
1210  return nullptr;
1211 
1212  SmallString<256> buf;
1213  llvm::raw_svector_ostream Out(buf);
1214 
1215  if (!CallStackMessage.empty()) {
1216  Out << CallStackMessage;
1217  } else {
1218  bool DidDescribe = describeCodeDecl(Out, Callee,
1219  /*ExtendedDescription=*/false,
1220  "Returning from ");
1221  if (!DidDescribe)
1222  Out << "Returning to caller";
1223  }
1224 
1225  assert(callReturn.asLocation().isValid());
1226  return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
1227 }
1228 
1229 static void compute_path_size(const PathPieces &pieces, unsigned &size) {
1230  for (const auto &I : pieces) {
1231  const PathDiagnosticPiece *piece = I.get();
1232  if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
1233  compute_path_size(cp->path, size);
1234  else
1235  ++size;
1236  }
1237 }
1238 
1240  unsigned size = 0;
1241  compute_path_size(path, size);
1242  return size;
1243 }
1244 
1245 //===----------------------------------------------------------------------===//
1246 // FoldingSet profiling methods.
1247 //===----------------------------------------------------------------------===//
1248 
1249 void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
1250  ID.AddInteger(Range.getBegin().getRawEncoding());
1251  ID.AddInteger(Range.getEnd().getRawEncoding());
1252  ID.AddInteger(Loc.getRawEncoding());
1253 }
1254 
1255 void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1256  ID.AddInteger((unsigned) getKind());
1257  ID.AddString(str);
1258  // FIXME: Add profiling support for code hints.
1259  ID.AddInteger((unsigned) getDisplayHint());
1260  ArrayRef<SourceRange> Ranges = getRanges();
1261  for (const auto &I : Ranges) {
1262  ID.AddInteger(I.getBegin().getRawEncoding());
1263  ID.AddInteger(I.getEnd().getRawEncoding());
1264  }
1265 }
1266 
1267 void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1269  for (const auto &I : path)
1270  ID.Add(*I);
1271 }
1272 
1273 void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1275  ID.Add(Pos);
1276 }
1277 
1278 void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1280  for (const auto &I : *this)
1281  ID.Add(I);
1282 }
1283 
1284 void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1286  for (const auto &I : subPieces)
1287  ID.Add(*I);
1288 }
1289 
1290 void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
1292 }
1293 
1294 void PathDiagnosticPopUpPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1296 }
1297 
1298 void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
1299  ID.Add(getLocation());
1300  ID.AddString(BugType);
1301  ID.AddString(VerboseDesc);
1302  ID.AddString(Category);
1303 }
1304 
1305 void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1306  Profile(ID);
1307  for (const auto &I : path)
1308  ID.Add(*I);
1309  for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1310  ID.AddString(*I);
1311 }
1312 
1314 
1316  if (!N)
1317  return getMessageForSymbolNotFound();
1318 
1319  ProgramPoint P = N->getLocation();
1320  CallExitEnd CExit = P.castAs<CallExitEnd>();
1321 
1322  // FIXME: Use CallEvent to abstract this over all calls.
1323  const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
1324  const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
1325  if (!CE)
1326  return {};
1327 
1328  // Check if one of the parameters are set to the interesting symbol.
1329  unsigned ArgIndex = 0;
1330  for (CallExpr::const_arg_iterator I = CE->arg_begin(),
1331  E = CE->arg_end(); I != E; ++I, ++ArgIndex){
1332  SVal SV = N->getSVal(*I);
1333 
1334  // Check if the variable corresponding to the symbol is passed by value.
1335  SymbolRef AS = SV.getAsLocSymbol();
1336  if (AS == Sym) {
1337  return getMessageForArg(*I, ArgIndex);
1338  }
1339 
1340  // Check if the parameter is a pointer to the symbol.
1342  // Do not attempt to dereference void*.
1343  if ((*I)->getType()->isVoidPointerType())
1344  continue;
1345  SVal PSV = N->getState()->getSVal(Reg->getRegion());
1346  SymbolRef AS = PSV.getAsLocSymbol();
1347  if (AS == Sym) {
1348  return getMessageForArg(*I, ArgIndex);
1349  }
1350  }
1351  }
1352 
1353  // Check if we are returning the interesting symbol.
1354  SVal SV = N->getSVal(CE);
1355  SymbolRef RetSym = SV.getAsLocSymbol();
1356  if (RetSym == Sym) {
1357  return getMessageForReturn(CE);
1358  }
1359 
1360  return getMessageForSymbolNotFound();
1361 }
1362 
1364  unsigned ArgIndex) {
1365  // Printed parameters start at 1, not 0.
1366  ++ArgIndex;
1367 
1368  SmallString<200> buf;
1369  llvm::raw_svector_ostream os(buf);
1370 
1371  os << Msg << " via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1372  << " parameter";
1373 
1374  return os.str();
1375 }
1376 
1377 LLVM_DUMP_METHOD void PathPieces::dump() const {
1378  unsigned index = 0;
1379  for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
1380  llvm::errs() << "[" << index++ << "] ";
1381  (*I)->dump();
1382  llvm::errs() << "\n";
1383  }
1384 }
1385 
1386 LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const {
1387  llvm::errs() << "CALL\n--------------\n";
1388 
1389  if (const Stmt *SLoc = getLocation().getStmtOrNull())
1390  SLoc->dump();
1391  else if (const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee()))
1392  llvm::errs() << *ND << "\n";
1393  else
1394  getLocation().dump();
1395 }
1396 
1397 LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const {
1398  llvm::errs() << "EVENT\n--------------\n";
1399  llvm::errs() << getString() << "\n";
1400  llvm::errs() << " ---- at ----\n";
1401  getLocation().dump();
1402 }
1403 
1404 LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const {
1405  llvm::errs() << "CONTROL\n--------------\n";
1406  getStartLocation().dump();
1407  llvm::errs() << " ---- to ----\n";
1408  getEndLocation().dump();
1409 }
1410 
1411 LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
1412  llvm::errs() << "MACRO\n--------------\n";
1413  // FIXME: Print which macro is being invoked.
1414 }
1415 
1416 LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const {
1417  llvm::errs() << "NOTE\n--------------\n";
1418  llvm::errs() << getString() << "\n";
1419  llvm::errs() << " ---- at ----\n";
1420  getLocation().dump();
1421 }
1422 
1423 LLVM_DUMP_METHOD void PathDiagnosticPopUpPiece::dump() const {
1424  llvm::errs() << "POP-UP\n--------------\n";
1425  llvm::errs() << getString() << "\n";
1426  llvm::errs() << " ---- at ----\n";
1427  getLocation().dump();
1428 }
1429 
1430 LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const {
1431  if (!isValid()) {
1432  llvm::errs() << "<INVALID>\n";
1433  return;
1434  }
1435 
1436  switch (K) {
1437  case RangeK:
1438  // FIXME: actually print the range.
1439  llvm::errs() << "<range>\n";
1440  break;
1441  case SingleLocK:
1442  asLocation().dump();
1443  llvm::errs() << "\n";
1444  break;
1445  case StmtK:
1446  if (S)
1447  S->dump();
1448  else
1449  llvm::errs() << "<NULL STMT>\n";
1450  break;
1451  case DeclK:
1452  if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
1453  llvm::errs() << *ND << "\n";
1454  else if (isa<BlockDecl>(D))
1455  // FIXME: Make this nicer.
1456  llvm::errs() << "<block>\n";
1457  else if (D)
1458  llvm::errs() << "<unknown decl>\n";
1459  else
1460  llvm::errs() << "<NULL DECL>\n";
1461  break;
1462  }
1463 }
SourceLocation getRBracLoc() const
Definition: Stmt.h:1403
Represents C++ allocator call.
Definition: CFG.h:239
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
Expr * getInit() const
Get the initializer.
Definition: DeclCXX.h:2536
static Optional< bool > compareMacro(const PathDiagnosticMacroPiece &X, const PathDiagnosticMacroPiece &Y)
const Stmt * getStmt() const
Definition: CFG.h:132
Stmt * getBody() const
Get the body of the Declaration.
ArrayRef< TemplateArgument > getPackAsArray() const
Return the array of arguments in this template argument pack.
Definition: TemplateBase.h:365
Defines the clang::FileManager interface and associated types.
static void compute_path_size(const PathPieces &pieces, unsigned &size)
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:986
FullSourceLoc getExpansionLoc() const
Stmt - This represents one statement.
Definition: Stmt.h:66
CFGBlock & getEntry()
Definition: CFG.h:1118
C Language Family Type Representation.
Defines the SourceManager interface.
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:88
Represents a point when we begin processing an inlined call.
Definition: ProgramPoint.h:630
static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the beginning of the compound statement.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:421
Defines the C++ template declaration subclasses.
StringRef P
void Profile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, independent of the path it references.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
Represents C++ object destructor generated from a call to delete.
Definition: CFG.h:408
std::shared_ptr< PathDiagnosticEventPiece > getCallEnterWithinCallerEvent() const
virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex)
Produces the message of the following form: &#39;Msg via Nth parameter&#39;.
void Profile(llvm::FoldingSetNodeID &ID) const
A Range represents the closed range [from, to].
Represents a program point just before an implicit call event.
Definition: ProgramPoint.h:583
SourceLocation getEndLoc() const LLVM_READONLY
Definition: DeclBase.h:425
PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type...
Definition: CFG.h:98
const ProgramStateRef & getState() const
static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the end of the compound statement.
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
Definition: SVals.cpp:85
SourceLocation getColonLoc() const
Definition: Expr.h:3693
FileID getFileID() const
const Stmt * getTriggerStmt() const
Definition: CFG.h:393
Describes how types, statements, expressions, and declarations should be printed. ...
Definition: PrettyPrinter.h:37
static PathDiagnosticLocation createDeclEnd(const LocationContext *LC, const SourceManager &SM)
Constructs a location for the end of the enclosing declaration body.
Defines the clang::Expr interface and subclasses for C++ expressions.
static PathDiagnosticLocation createSingleLocation(const PathDiagnosticLocation &PDL)
Convert the given location into a single kind location.
long i
Definition: xmmintrin.h:1456
Symbolic value.
Definition: SymExpr.h:29
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:269
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:263
AnalysisDeclContext contains the context data for the function or method under analysis.
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
Definition: CFG.h:383
static const LocationContext * findTopAutosynthesizedParentContext(const LocationContext *LC)
int Category
Definition: Format.cpp:1712
static bool isInCodeFile(SourceLocation SL, const SourceManager &SM)
void Profile(llvm::FoldingSetNodeID &ID) const override
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:49
Optional< T > getLocationAs() const LLVM_LVALUE_FUNCTION
Represents a point when we start the call exit sequence (for inlined call).
Definition: ProgramPoint.h:668
bool isInvalid() const
static PathDiagnosticCallPiece * getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP, const SourceManager &SMgr)
BinaryOperatorKind
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
std::vector< std::pair< StringRef, StringRef > > ConsumerFiles
SourceLocation getLBracLoc() const
Definition: Stmt.h:1402
void Profile(llvm::FoldingSetNodeID &ID) const override
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
const LocationContext * getLocationContext() const
const LocationContext * getParent() const
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3405
std::string getMessage(const ExplodedNode *N) override
Search the call expression for the symbol Sym and dispatch the &#39;getMessageForX()&#39; methods to construc...
Represents a point after we ran remove dead bindings AFTER processing the given statement.
Definition: ProgramPoint.h:489
b
Definition: emmintrin.h:321
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
static Optional< bool > comparePath(const PathPieces &X, const PathPieces &Y)
virtual PathDiagnosticLocation getLocation() const =0
static SourceLocation getValidSourceLocation(const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEnd=false)
const CFGBlock * getCallSiteBlock() const
static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME, const SourceManager &SM)
For member expressions, return the location of the &#39;.
CFG * getParent() const
Definition: CFG.h:878
NodeId Parent
Definition: ASTDiff.cpp:191
CXXCtorInitializer * getInitializer() const
Definition: CFG.h:224
void print(const PrintingPolicy &Policy, raw_ostream &Out) const
Print this template argument to the given output stream.
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:3703
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1310
const Stmt * getCallSite() const
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
Represents a single basic block in a source-level CFG.
Definition: CFG.h:570
PDFileEntry::ConsumerFiles * getFiles(const PathDiagnostic &PD)
Represents a point when we finish the call exit sequence (for inlined call).
Definition: ProgramPoint.h:688
DisplayHint getDisplayHint() const
getDisplayHint - Return a hint indicating where the diagnostic should be displayed by the PathDiagnos...
void FullProfile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, including its path.
This represents one expression.
Definition: Expr.h:108
Stmt * getTerminatorCondition(bool StripParens=true)
Definition: CFG.cpp:5618
static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y)
std::pair< FileID, unsigned > getDecomposedLoc() const
Decompose the specified location into a raw FileID + Offset pair.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
ExplodedNode * getFirstSucc()
const SourceManager & getManager() const
const SourceManager & getManager() const
static PathDiagnosticLocation getLocationForCaller(const StackFrameContext *SFC, const LocationContext *CallerCtx, const SourceManager &SM)
static const Stmt * getNextStmt(const ExplodedNode *N)
Retrieve the statement corresponding to the successor node.
static void describeTemplateParameters(raw_ostream &Out, const ArrayRef< TemplateArgument > TAList, const LangOptions &LO, StringRef Prefix=StringRef(), StringRef Postfix=StringRef())
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:2595
void resetDiagnosticLocationToMainFile()
If the last piece of the report point to the header file, resets the location of the report to be the...
bool isBodyAutosynthesized() const
Checks if the body of the Decl is generated by the BodyFarm.
SourceLocation getEnd() const
SourceLocation getMemberLoc() const
getMemberLoc - Return the location of the "member", in X->F, it is the location of &#39;F&#39;...
Definition: Expr.h:2996
const SourceManager & SM
Definition: Format.cpp:1570
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:111
static Optional< bool > comparePiece(const PathDiagnosticPiece &X, const PathDiagnosticPiece &Y)
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:276
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
static PathDiagnosticLocation createDeclBegin(const LocationContext *LC, const SourceManager &SM)
Create a location for the beginning of the enclosing declaration body.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
Kind getKind() const
Definition: CFG.h:118
std::shared_ptr< PathDiagnosticEventPiece > getCallEnterEvent() const
Kind
bool isBeforeInTranslationUnitThan(SourceLocation Loc) const
Determines the order of 2 source locations in the translation unit.
Encodes a location in the source.
SourceLocation getOperatorLoc() const
Definition: Expr.h:3437
StringRef getName() const
Definition: FileManager.h:83
std::shared_ptr< PathDiagnosticEventPiece > getCallExitEvent() const
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type...
Definition: ProgramPoint.h:140
void setCallee(const CallEnter &CE, const SourceManager &SM)
Cached information about one file (either on disk or in the virtual file system). ...
Definition: FileManager.h:59
std::deque< std::string >::const_iterator meta_iterator
static PathDiagnosticLocation createConditionalColonLoc(const ConditionalOperator *CO, const SourceManager &SM)
std::pair< bool, bool > isInTheSameTranslationUnit(std::pair< FileID, unsigned > &LOffs, std::pair< FileID, unsigned > &ROffs) const
Determines whether the two decomposed source location is in the same translation unit.
static bool describeCodeDecl(raw_ostream &Out, const Decl *D, bool ExtendedDescription, StringRef Prefix=StringRef())
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:75
static PathDiagnosticLocation createEnd(const Stmt *S, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)
Create a location for the end of the statement.
const Decl * getDecl() const
PathDiagnosticLocation getLocation() const override
SVal getSVal(const Stmt *S) const
Get the value of an arbitrary expression at this node.
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
Definition: CFG.h:109
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Represents a template argument.
Definition: TemplateBase.h:50
ConsumerFiles files
A vector of <consumer,file> pairs.
ArrayRef< SourceRange > getRanges() const
Return the SourceRanges associated with this PathDiagnosticPiece.
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
Represents a program point just after an implicit call event.
Definition: ProgramPoint.h:600
virtual void Profile(llvm::FoldingSetNodeID &ID) const
static void describeClass(raw_ostream &Out, const CXXRecordDecl *D, StringRef Prefix=StringRef())
const StackFrameContext * getCalleeContext() const
Definition: ProgramPoint.h:640
void FlushDiagnostics(FilesMade *FilesMade)
const StackFrameContext * getCalleeContext() const
Definition: ProgramPoint.h:695
StmtClass getStmtClass() const
Definition: Stmt.h:1087
bool isVirtualBaseBranch() const
Definition: CFG.h:539
static Optional< bool > compareCall(const PathDiagnosticCallPiece &X, const PathDiagnosticCallPiece &Y)
void Profile(llvm::FoldingSetNodeID &ID) const override
const Decl * getDecl() const
const CXXDeleteExpr * getDeleteExpr() const
Definition: CFG.h:418
bool isMacroID() const
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
Iterator for iterating over Stmt * arrays that contain only T *.
Definition: Stmt.h:1042
void dump() const
Dumps the specified AST fragment and all subtrees to llvm::errs().
Definition: ASTDumper.cpp:243
static void describeTemplateParameter(raw_ostream &Out, const TemplateArgument &TArg, const LangOptions &LO)
const LocationContext * getLocationContext() const
Definition: ProgramPoint.h:179
void Profile(llvm::FoldingSetNodeID &ID) const override
static std::shared_ptr< PathDiagnosticCallPiece > construct(const CallExitEnd &CE, const SourceManager &SM)
A template argument list.
Definition: DeclTemplate.h:214
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:14134
const CXXNewExpr * getAllocatorExpr() const
Definition: CFG.h:245
ArgKind getKind() const
Return the kind of stored template argument.
Definition: TemplateBase.h:234
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:2807
Defines the clang::SourceLocation class and associated facilities.
Represents a C++ struct/union/class.
Definition: DeclCXX.h:300
bool isValid() const
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
Create a location corresponding to the next valid ExplodedNode as end of path location.
Represents a top-level expression in a basic block.
Definition: CFG.h:55
static StringRef StripTrailingDots(StringRef s)
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:251
FullSourceLoc getSpellingLoc() const
A SourceLocation and its associated SourceManager.
void Profile(llvm::FoldingSetNodeID &ID) const override
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:1728
void addDiagnostic(const PathDiagnostic &PD, StringRef ConsumerName, StringRef fileName)
Represents C++ base or member initializer from constructor&#39;s initialization list. ...
Definition: CFG.h:219
A trivial tuple used to represent a source range.
This represents a decl that may have a name.
Definition: Decl.h:248
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:151
CFGTerminator getTerminator() const
Definition: CFG.h:858
AnalysisDeclContext * getAnalysisDeclContext() const
SourceLocation getBegin() const
static Optional< bool > compareControlFlow(const PathDiagnosticControlFlowPiece &X, const PathDiagnosticControlFlowPiece &Y)
This class handles loading and caching of source files into memory.
Represents C++ object destructor implicitly generated at the end of full expression for temporary obj...
Definition: CFG.h:476
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
Definition: DeclBase.cpp:894
SourceLocation getLocation() const
Definition: DeclBase.h:429
static bool compareCrossTUSourceLocs(FullSourceLoc XL, FullSourceLoc YL)
unsigned full_size()
Return the unrolled size of the path.
void Profile(llvm::FoldingSetNodeID &ID) const override