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