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