]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
Update clang to trunk r256633.
[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 (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end();
33        I!=E; ++I) {
34     if (isa<PathDiagnosticEventPiece>(*I))
35       return true;
36     if (PathDiagnosticMacroPiece *MP = dyn_cast<PathDiagnosticMacroPiece>(*I))
37       if (MP->containsEvent())
38         return true;
39   }
40   return false;
41 }
42
43 static StringRef StripTrailingDots(StringRef s) {
44   for (StringRef::size_type i = s.size(); i != 0; --i)
45     if (s[i - 1] != '.')
46       return s.substr(0, i);
47   return "";
48 }
49
50 PathDiagnosticPiece::PathDiagnosticPiece(StringRef s,
51                                          Kind k, DisplayHint hint)
52   : str(StripTrailingDots(s)), kind(k), Hint(hint),
53     LastInMainSourceFile(false) {}
54
55 PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
56   : kind(k), Hint(hint), LastInMainSourceFile(false) {}
57
58 PathDiagnosticPiece::~PathDiagnosticPiece() {}
59 PathDiagnosticEventPiece::~PathDiagnosticEventPiece() {}
60 PathDiagnosticCallPiece::~PathDiagnosticCallPiece() {}
61 PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {}
62 PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {}
63
64
65 void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
66                            bool ShouldFlattenMacros) const {
67   for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
68     PathDiagnosticPiece *Piece = I->get();
69
70     switch (Piece->getKind()) {
71     case PathDiagnosticPiece::Call: {
72       PathDiagnosticCallPiece *Call = cast<PathDiagnosticCallPiece>(Piece);
73       IntrusiveRefCntPtr<PathDiagnosticEventPiece> CallEnter =
74         Call->getCallEnterEvent();
75       if (CallEnter)
76         Current.push_back(CallEnter);
77       Call->path.flattenTo(Primary, Primary, ShouldFlattenMacros);
78       IntrusiveRefCntPtr<PathDiagnosticEventPiece> callExit =
79         Call->getCallExitEvent();
80       if (callExit)
81         Current.push_back(callExit);
82       break;
83     }
84     case PathDiagnosticPiece::Macro: {
85       PathDiagnosticMacroPiece *Macro = cast<PathDiagnosticMacroPiece>(Piece);
86       if (ShouldFlattenMacros) {
87         Macro->subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
88       } else {
89         Current.push_back(Piece);
90         PathPieces NewPath;
91         Macro->subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
92         // FIXME: This probably shouldn't mutate the original path piece.
93         Macro->subPieces = NewPath;
94       }
95       break;
96     }
97     case PathDiagnosticPiece::Event:
98     case PathDiagnosticPiece::ControlFlow:
99       Current.push_back(Piece);
100       break;
101     }
102   }
103 }
104
105
106 PathDiagnostic::~PathDiagnostic() {}
107
108 PathDiagnostic::PathDiagnostic(StringRef CheckName, const Decl *declWithIssue,
109                                StringRef bugtype, StringRef verboseDesc,
110                                StringRef shortDesc, StringRef category,
111                                PathDiagnosticLocation LocationToUnique,
112                                const Decl *DeclToUnique)
113   : CheckName(CheckName),
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 nullptr;
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 nullptr;
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 nullptr;
152 }
153
154 void PathDiagnostic::resetDiagnosticLocationToMainFile() {
155   if (path.empty())
156     return;
157
158   PathDiagnosticPiece *LastP = path.back().get();
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(
199     std::unique_ptr<PathDiagnostic> D) {
200   if (!D || D->path.empty())
201     return;
202
203   // We need to flatten the locations (convert Stmt* to locations) because
204   // the referenced statements may be freed by the time the diagnostics
205   // are emitted.
206   D->flattenLocations();
207
208   // If the PathDiagnosticConsumer does not support diagnostics that
209   // cross file boundaries, prune out such diagnostics now.
210   if (!supportsCrossFileDiagnostics()) {
211     // Verify that the entire path is from the same FileID.
212     FileID FID;
213     const SourceManager &SMgr = D->path.front()->getLocation().getManager();
214     SmallVector<const PathPieces *, 5> WorkList;
215     WorkList.push_back(&D->path);
216
217     while (!WorkList.empty()) {
218       const PathPieces &path = *WorkList.pop_back_val();
219
220       for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E;
221            ++I) {
222         const PathDiagnosticPiece *piece = I->get();
223         FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc();
224
225         if (FID.isInvalid()) {
226           FID = SMgr.getFileID(L);
227         } else if (SMgr.getFileID(L) != FID)
228           return; // FIXME: Emit a warning?
229
230         // Check the source ranges.
231         ArrayRef<SourceRange> Ranges = piece->getRanges();
232         for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
233                                              E = Ranges.end(); I != E; ++I) {
234           SourceLocation L = SMgr.getExpansionLoc(I->getBegin());
235           if (!L.isFileID() || SMgr.getFileID(L) != FID)
236             return; // FIXME: Emit a warning?
237           L = SMgr.getExpansionLoc(I->getEnd());
238           if (!L.isFileID() || SMgr.getFileID(L) != FID)
239             return; // FIXME: Emit a warning?
240         }
241
242         if (const PathDiagnosticCallPiece *call =
243             dyn_cast<PathDiagnosticCallPiece>(piece)) {
244           WorkList.push_back(&call->path);
245         }
246         else if (const PathDiagnosticMacroPiece *macro =
247                  dyn_cast<PathDiagnosticMacroPiece>(piece)) {
248           WorkList.push_back(&macro->subPieces);
249         }
250       }
251     }
252
253     if (FID.isInvalid())
254       return; // FIXME: Emit a warning?
255   }
256
257   // Profile the node to see if we already have something matching it
258   llvm::FoldingSetNodeID profile;
259   D->Profile(profile);
260   void *InsertPos = nullptr;
261
262   if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
263     // Keep the PathDiagnostic with the shorter path.
264     // Note, the enclosing routine is called in deterministic order, so the
265     // results will be consistent between runs (no reason to break ties if the
266     // size is the same).
267     const unsigned orig_size = orig->full_size();
268     const unsigned new_size = D->full_size();
269     if (orig_size <= new_size)
270       return;
271
272     assert(orig != D.get());
273     Diags.RemoveNode(orig);
274     delete orig;
275   }
276
277   Diags.InsertNode(D.release());
278 }
279
280 static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y);
281 static Optional<bool>
282 compareControlFlow(const PathDiagnosticControlFlowPiece &X,
283                    const PathDiagnosticControlFlowPiece &Y) {
284   FullSourceLoc XSL = X.getStartLocation().asLocation();
285   FullSourceLoc YSL = Y.getStartLocation().asLocation();
286   if (XSL != YSL)
287     return XSL.isBeforeInTranslationUnitThan(YSL);
288   FullSourceLoc XEL = X.getEndLocation().asLocation();
289   FullSourceLoc YEL = Y.getEndLocation().asLocation();
290   if (XEL != YEL)
291     return XEL.isBeforeInTranslationUnitThan(YEL);
292   return None;
293 }
294
295 static Optional<bool> compareMacro(const PathDiagnosticMacroPiece &X,
296                                    const PathDiagnosticMacroPiece &Y) {
297   return comparePath(X.subPieces, Y.subPieces);
298 }
299
300 static Optional<bool> compareCall(const PathDiagnosticCallPiece &X,
301                                   const PathDiagnosticCallPiece &Y) {
302   FullSourceLoc X_CEL = X.callEnter.asLocation();
303   FullSourceLoc Y_CEL = Y.callEnter.asLocation();
304   if (X_CEL != Y_CEL)
305     return X_CEL.isBeforeInTranslationUnitThan(Y_CEL);
306   FullSourceLoc X_CEWL = X.callEnterWithin.asLocation();
307   FullSourceLoc Y_CEWL = Y.callEnterWithin.asLocation();
308   if (X_CEWL != Y_CEWL)
309     return X_CEWL.isBeforeInTranslationUnitThan(Y_CEWL);
310   FullSourceLoc X_CRL = X.callReturn.asLocation();
311   FullSourceLoc Y_CRL = Y.callReturn.asLocation();
312   if (X_CRL != Y_CRL)
313     return X_CRL.isBeforeInTranslationUnitThan(Y_CRL);
314   return comparePath(X.path, Y.path);
315 }
316
317 static Optional<bool> comparePiece(const PathDiagnosticPiece &X,
318                                    const PathDiagnosticPiece &Y) {
319   if (X.getKind() != Y.getKind())
320     return X.getKind() < Y.getKind();
321
322   FullSourceLoc XL = X.getLocation().asLocation();
323   FullSourceLoc YL = Y.getLocation().asLocation();
324   if (XL != YL)
325     return XL.isBeforeInTranslationUnitThan(YL);
326
327   if (X.getString() != Y.getString())
328     return X.getString() < Y.getString();
329
330   if (X.getRanges().size() != Y.getRanges().size())
331     return X.getRanges().size() < Y.getRanges().size();
332
333   const SourceManager &SM = XL.getManager();
334
335   for (unsigned i = 0, n = X.getRanges().size(); i < n; ++i) {
336     SourceRange XR = X.getRanges()[i];
337     SourceRange YR = Y.getRanges()[i];
338     if (XR != YR) {
339       if (XR.getBegin() != YR.getBegin())
340         return SM.isBeforeInTranslationUnit(XR.getBegin(), YR.getBegin());
341       return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd());
342     }
343   }
344
345   switch (X.getKind()) {
346     case clang::ento::PathDiagnosticPiece::ControlFlow:
347       return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X),
348                                 cast<PathDiagnosticControlFlowPiece>(Y));
349     case clang::ento::PathDiagnosticPiece::Event:
350       return None;
351     case clang::ento::PathDiagnosticPiece::Macro:
352       return compareMacro(cast<PathDiagnosticMacroPiece>(X),
353                           cast<PathDiagnosticMacroPiece>(Y));
354     case clang::ento::PathDiagnosticPiece::Call:
355       return compareCall(cast<PathDiagnosticCallPiece>(X),
356                          cast<PathDiagnosticCallPiece>(Y));
357   }
358   llvm_unreachable("all cases handled");
359 }
360
361 static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) {
362   if (X.size() != Y.size())
363     return X.size() < Y.size();
364
365   PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
366   PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
367
368   for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) {
369     Optional<bool> b = comparePiece(**X_I, **Y_I);
370     if (b.hasValue())
371       return b.getValue();
372   }
373
374   return None;
375 }
376
377 static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
378   FullSourceLoc XL = X.getLocation().asLocation();
379   FullSourceLoc YL = Y.getLocation().asLocation();
380   if (XL != YL)
381     return XL.isBeforeInTranslationUnitThan(YL);
382   if (X.getBugType() != Y.getBugType())
383     return X.getBugType() < Y.getBugType();
384   if (X.getCategory() != Y.getCategory())
385     return X.getCategory() < Y.getCategory();
386   if (X.getVerboseDescription() != Y.getVerboseDescription())
387     return X.getVerboseDescription() < Y.getVerboseDescription();
388   if (X.getShortDescription() != Y.getShortDescription())
389     return X.getShortDescription() < Y.getShortDescription();
390   if (X.getDeclWithIssue() != Y.getDeclWithIssue()) {
391     const Decl *XD = X.getDeclWithIssue();
392     if (!XD)
393       return true;
394     const Decl *YD = Y.getDeclWithIssue();
395     if (!YD)
396       return false;
397     SourceLocation XDL = XD->getLocation();
398     SourceLocation YDL = YD->getLocation();
399     if (XDL != YDL) {
400       const SourceManager &SM = XL.getManager();
401       return SM.isBeforeInTranslationUnit(XDL, YDL);
402     }
403   }
404   PathDiagnostic::meta_iterator XI = X.meta_begin(), XE = X.meta_end();
405   PathDiagnostic::meta_iterator YI = Y.meta_begin(), YE = Y.meta_end();
406   if (XE - XI != YE - YI)
407     return (XE - XI) < (YE - YI);
408   for ( ; XI != XE ; ++XI, ++YI) {
409     if (*XI != *YI)
410       return (*XI) < (*YI);
411   }
412   Optional<bool> b = comparePath(X.path, Y.path);
413   assert(b.hasValue());
414   return b.getValue();
415 }
416
417 void PathDiagnosticConsumer::FlushDiagnostics(
418                                      PathDiagnosticConsumer::FilesMade *Files) {
419   if (flushed)
420     return;
421
422   flushed = true;
423
424   std::vector<const PathDiagnostic *> BatchDiags;
425   for (llvm::FoldingSet<PathDiagnostic>::iterator it = Diags.begin(),
426        et = Diags.end(); it != et; ++it) {
427     const PathDiagnostic *D = &*it;
428     BatchDiags.push_back(D);
429   }
430
431   // Sort the diagnostics so that they are always emitted in a deterministic
432   // order.
433   int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
434       [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
435         assert(*X != *Y && "PathDiagnostics not uniqued!");
436         if (compare(**X, **Y))
437           return -1;
438         assert(compare(**Y, **X) && "Not a total order!");
439         return 1;
440       };
441   array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
442
443   FlushDiagnosticsImpl(BatchDiags, Files);
444
445   // Delete the flushed diagnostics.
446   for (std::vector<const PathDiagnostic *>::iterator it = BatchDiags.begin(),
447        et = BatchDiags.end(); it != et; ++it) {
448     const PathDiagnostic *D = *it;
449     delete D;
450   }
451
452   // Clear out the FoldingSet.
453   Diags.clear();
454 }
455
456 PathDiagnosticConsumer::FilesMade::~FilesMade() {
457   for (PDFileEntry &Entry : Set)
458     Entry.~PDFileEntry();
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 = Set.FindNodeOrInsertPos(NodeID, InsertPos);
468   if (!Entry) {
469     Entry = Alloc.Allocate<PDFileEntry>();
470     Entry = new (Entry) PDFileEntry(NodeID);
471     Set.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 = Set.FindNodeOrInsertPos(NodeID, InsertPos);
489   if (!Entry)
490     return nullptr;
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   case CFGElement::NewAllocator:
575     llvm_unreachable("not yet implemented!");
576   }
577
578   llvm_unreachable("Unknown CFGElement kind");
579 }
580
581
582 PathDiagnosticLocation
583   PathDiagnosticLocation::createBegin(const Decl *D,
584                                       const SourceManager &SM) {
585   return PathDiagnosticLocation(D->getLocStart(), SM, SingleLocK);
586 }
587
588 PathDiagnosticLocation
589   PathDiagnosticLocation::createBegin(const Stmt *S,
590                                       const SourceManager &SM,
591                                       LocationOrAnalysisDeclContext LAC) {
592   return PathDiagnosticLocation(getValidSourceLocation(S, LAC),
593                                 SM, SingleLocK);
594 }
595
596
597 PathDiagnosticLocation
598 PathDiagnosticLocation::createEnd(const Stmt *S,
599                                   const SourceManager &SM,
600                                   LocationOrAnalysisDeclContext LAC) {
601   if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(S))
602     return createEndBrace(CS, SM);
603   return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
604                                 SM, SingleLocK);
605 }
606
607 PathDiagnosticLocation
608   PathDiagnosticLocation::createOperatorLoc(const BinaryOperator *BO,
609                                             const SourceManager &SM) {
610   return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
611 }
612
613 PathDiagnosticLocation
614   PathDiagnosticLocation::createConditionalColonLoc(
615                                             const ConditionalOperator *CO,
616                                             const SourceManager &SM) {
617   return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
618 }
619
620
621 PathDiagnosticLocation
622   PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME,
623                                           const SourceManager &SM) {
624   return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
625 }
626
627 PathDiagnosticLocation
628   PathDiagnosticLocation::createBeginBrace(const CompoundStmt *CS,
629                                            const SourceManager &SM) {
630   SourceLocation L = CS->getLBracLoc();
631   return PathDiagnosticLocation(L, SM, SingleLocK);
632 }
633
634 PathDiagnosticLocation
635   PathDiagnosticLocation::createEndBrace(const CompoundStmt *CS,
636                                          const SourceManager &SM) {
637   SourceLocation L = CS->getRBracLoc();
638   return PathDiagnosticLocation(L, SM, SingleLocK);
639 }
640
641 PathDiagnosticLocation
642   PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
643                                           const SourceManager &SM) {
644   // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
645   if (const CompoundStmt *CS =
646         dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
647     if (!CS->body_empty()) {
648       SourceLocation Loc = (*CS->body_begin())->getLocStart();
649       return PathDiagnosticLocation(Loc, SM, SingleLocK);
650     }
651
652   return PathDiagnosticLocation();
653 }
654
655 PathDiagnosticLocation
656   PathDiagnosticLocation::createDeclEnd(const LocationContext *LC,
657                                         const SourceManager &SM) {
658   SourceLocation L = LC->getDecl()->getBodyRBrace();
659   return PathDiagnosticLocation(L, SM, SingleLocK);
660 }
661
662 PathDiagnosticLocation
663   PathDiagnosticLocation::create(const ProgramPoint& P,
664                                  const SourceManager &SMng) {
665
666   const Stmt* S = nullptr;
667   if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
668     const CFGBlock *BSrc = BE->getSrc();
669     S = BSrc->getTerminatorCondition();
670   } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
671     S = SP->getStmt();
672     if (P.getAs<PostStmtPurgeDeadSymbols>())
673       return PathDiagnosticLocation::createEnd(S, SMng, P.getLocationContext());
674   } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
675     return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
676                                   SMng);
677   } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
678     return PathDiagnosticLocation(PIE->getLocation(), SMng);
679   } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
680     return getLocationForCaller(CE->getCalleeContext(),
681                                 CE->getLocationContext(),
682                                 SMng);
683   } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
684     return getLocationForCaller(CEE->getCalleeContext(),
685                                 CEE->getLocationContext(),
686                                 SMng);
687   } else {
688     llvm_unreachable("Unexpected ProgramPoint");
689   }
690
691   return PathDiagnosticLocation(S, SMng, P.getLocationContext());
692 }
693
694 const Stmt *PathDiagnosticLocation::getStmt(const ExplodedNode *N) {
695   ProgramPoint P = N->getLocation();
696   if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
697     return SP->getStmt();
698   if (Optional<BlockEdge> BE = P.getAs<BlockEdge>())
699     return BE->getSrc()->getTerminator();
700   if (Optional<CallEnter> CE = P.getAs<CallEnter>())
701     return CE->getCallExpr();
702   if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>())
703     return CEE->getCalleeContext()->getCallSite();
704   if (Optional<PostInitializer> PIPP = P.getAs<PostInitializer>())
705     return PIPP->getInitializer()->getInit();
706
707   return nullptr;
708 }
709
710 const Stmt *PathDiagnosticLocation::getNextStmt(const ExplodedNode *N) {
711   for (N = N->getFirstSucc(); N; N = N->getFirstSucc()) {
712     if (const Stmt *S = getStmt(N)) {
713       // Check if the statement is '?' or '&&'/'||'.  These are "merges",
714       // not actual statement points.
715       switch (S->getStmtClass()) {
716         case Stmt::ChooseExprClass:
717         case Stmt::BinaryConditionalOperatorClass:
718         case Stmt::ConditionalOperatorClass:
719           continue;
720         case Stmt::BinaryOperatorClass: {
721           BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
722           if (Op == BO_LAnd || Op == BO_LOr)
723             continue;
724           break;
725         }
726         default:
727           break;
728       }
729       // We found the statement, so return it.
730       return S;
731     }
732   }
733
734   return nullptr;
735 }
736
737 PathDiagnosticLocation
738   PathDiagnosticLocation::createEndOfPath(const ExplodedNode *N,
739                                           const SourceManager &SM) {
740   assert(N && "Cannot create a location with a null node.");
741   const Stmt *S = getStmt(N);
742
743   if (!S) {
744     // If this is an implicit call, return the implicit call point location.
745     if (Optional<PreImplicitCall> PIE = N->getLocationAs<PreImplicitCall>())
746       return PathDiagnosticLocation(PIE->getLocation(), SM);
747     S = getNextStmt(N);
748   }
749
750   if (S) {
751     ProgramPoint P = N->getLocation();
752     const LocationContext *LC = N->getLocationContext();
753
754     // For member expressions, return the location of the '.' or '->'.
755     if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
756       return PathDiagnosticLocation::createMemberLoc(ME, SM);
757
758     // For binary operators, return the location of the operator.
759     if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
760       return PathDiagnosticLocation::createOperatorLoc(B, SM);
761
762     if (P.getAs<PostStmtPurgeDeadSymbols>())
763       return PathDiagnosticLocation::createEnd(S, SM, LC);
764
765     if (S->getLocStart().isValid())
766       return PathDiagnosticLocation(S, SM, LC);
767     return PathDiagnosticLocation(getValidSourceLocation(S, LC), SM);
768   }
769
770   return createDeclEnd(N->getLocationContext(), SM);
771 }
772
773 PathDiagnosticLocation PathDiagnosticLocation::createSingleLocation(
774                                            const PathDiagnosticLocation &PDL) {
775   FullSourceLoc L = PDL.asLocation();
776   return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
777 }
778
779 FullSourceLoc
780   PathDiagnosticLocation::genLocation(SourceLocation L,
781                                       LocationOrAnalysisDeclContext LAC) const {
782   assert(isValid());
783   // Note that we want a 'switch' here so that the compiler can warn us in
784   // case we add more cases.
785   switch (K) {
786     case SingleLocK:
787     case RangeK:
788       break;
789     case StmtK:
790       // Defensive checking.
791       if (!S)
792         break;
793       return FullSourceLoc(getValidSourceLocation(S, LAC),
794                            const_cast<SourceManager&>(*SM));
795     case DeclK:
796       // Defensive checking.
797       if (!D)
798         break;
799       return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
800   }
801
802   return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
803 }
804
805 PathDiagnosticRange
806   PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
807   assert(isValid());
808   // Note that we want a 'switch' here so that the compiler can warn us in
809   // case we add more cases.
810   switch (K) {
811     case SingleLocK:
812       return PathDiagnosticRange(SourceRange(Loc,Loc), true);
813     case RangeK:
814       break;
815     case StmtK: {
816       const Stmt *S = asStmt();
817       switch (S->getStmtClass()) {
818         default:
819           break;
820         case Stmt::DeclStmtClass: {
821           const DeclStmt *DS = cast<DeclStmt>(S);
822           if (DS->isSingleDecl()) {
823             // Should always be the case, but we'll be defensive.
824             return SourceRange(DS->getLocStart(),
825                                DS->getSingleDecl()->getLocation());
826           }
827           break;
828         }
829           // FIXME: Provide better range information for different
830           //  terminators.
831         case Stmt::IfStmtClass:
832         case Stmt::WhileStmtClass:
833         case Stmt::DoStmtClass:
834         case Stmt::ForStmtClass:
835         case Stmt::ChooseExprClass:
836         case Stmt::IndirectGotoStmtClass:
837         case Stmt::SwitchStmtClass:
838         case Stmt::BinaryConditionalOperatorClass:
839         case Stmt::ConditionalOperatorClass:
840         case Stmt::ObjCForCollectionStmtClass: {
841           SourceLocation L = getValidSourceLocation(S, LAC);
842           return SourceRange(L, L);
843         }
844       }
845       SourceRange R = S->getSourceRange();
846       if (R.isValid())
847         return R;
848       break;
849     }
850     case DeclK:
851       if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
852         return MD->getSourceRange();
853       if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
854         if (Stmt *Body = FD->getBody())
855           return Body->getSourceRange();
856       }
857       else {
858         SourceLocation L = D->getLocation();
859         return PathDiagnosticRange(SourceRange(L, L), true);
860       }
861   }
862
863   return SourceRange(Loc,Loc);
864 }
865
866 void PathDiagnosticLocation::flatten() {
867   if (K == StmtK) {
868     K = RangeK;
869     S = nullptr;
870     D = nullptr;
871   }
872   else if (K == DeclK) {
873     K = SingleLocK;
874     S = nullptr;
875     D = nullptr;
876   }
877 }
878
879 //===----------------------------------------------------------------------===//
880 // Manipulation of PathDiagnosticCallPieces.
881 //===----------------------------------------------------------------------===//
882
883 PathDiagnosticCallPiece *
884 PathDiagnosticCallPiece::construct(const ExplodedNode *N,
885                                    const CallExitEnd &CE,
886                                    const SourceManager &SM) {
887   const Decl *caller = CE.getLocationContext()->getDecl();
888   PathDiagnosticLocation pos = getLocationForCaller(CE.getCalleeContext(),
889                                                     CE.getLocationContext(),
890                                                     SM);
891   return new PathDiagnosticCallPiece(caller, pos);
892 }
893
894 PathDiagnosticCallPiece *
895 PathDiagnosticCallPiece::construct(PathPieces &path,
896                                    const Decl *caller) {
897   PathDiagnosticCallPiece *C = new PathDiagnosticCallPiece(path, caller);
898   path.clear();
899   path.push_front(C);
900   return C;
901 }
902
903 void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
904                                         const SourceManager &SM) {
905   const StackFrameContext *CalleeCtx = CE.getCalleeContext();
906   Callee = CalleeCtx->getDecl();
907
908   callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
909   callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
910 }
911
912 static inline void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
913                                  StringRef Prefix = StringRef()) {
914   if (!D->getIdentifier())
915     return;
916   Out << Prefix << '\'' << *D << '\'';
917 }
918
919 static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
920                              bool ExtendedDescription,
921                              StringRef Prefix = StringRef()) {
922   if (!D)
923     return false;
924
925   if (isa<BlockDecl>(D)) {
926     if (ExtendedDescription)
927       Out << Prefix << "anonymous block";
928     return ExtendedDescription;
929   }
930
931   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
932     Out << Prefix;
933     if (ExtendedDescription && !MD->isUserProvided()) {
934       if (MD->isExplicitlyDefaulted())
935         Out << "defaulted ";
936       else
937         Out << "implicit ";
938     }
939
940     if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(MD)) {
941       if (CD->isDefaultConstructor())
942         Out << "default ";
943       else if (CD->isCopyConstructor())
944         Out << "copy ";
945       else if (CD->isMoveConstructor())
946         Out << "move ";
947
948       Out << "constructor";
949       describeClass(Out, MD->getParent(), " for ");
950
951     } else if (isa<CXXDestructorDecl>(MD)) {
952       if (!MD->isUserProvided()) {
953         Out << "destructor";
954         describeClass(Out, MD->getParent(), " for ");
955       } else {
956         // Use ~Foo for explicitly-written destructors.
957         Out << "'" << *MD << "'";
958       }
959
960     } else if (MD->isCopyAssignmentOperator()) {
961         Out << "copy assignment operator";
962         describeClass(Out, MD->getParent(), " for ");
963
964     } else if (MD->isMoveAssignmentOperator()) {
965         Out << "move assignment operator";
966         describeClass(Out, MD->getParent(), " for ");
967
968     } else {
969       if (MD->getParent()->getIdentifier())
970         Out << "'" << *MD->getParent() << "::" << *MD << "'";
971       else
972         Out << "'" << *MD << "'";
973     }
974
975     return true;
976   }
977
978   Out << Prefix << '\'' << cast<NamedDecl>(*D) << '\'';
979   return true;
980 }
981
982 IntrusiveRefCntPtr<PathDiagnosticEventPiece>
983 PathDiagnosticCallPiece::getCallEnterEvent() const {
984   if (!Callee)
985     return nullptr;
986
987   SmallString<256> buf;
988   llvm::raw_svector_ostream Out(buf);
989
990   Out << "Calling ";
991   describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
992
993   assert(callEnter.asLocation().isValid());
994   return new PathDiagnosticEventPiece(callEnter, Out.str());
995 }
996
997 IntrusiveRefCntPtr<PathDiagnosticEventPiece>
998 PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
999   if (!callEnterWithin.asLocation().isValid())
1000     return nullptr;
1001   if (Callee->isImplicit() || !Callee->hasBody())
1002     return nullptr;
1003   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee))
1004     if (MD->isDefaulted())
1005       return nullptr;
1006
1007   SmallString<256> buf;
1008   llvm::raw_svector_ostream Out(buf);
1009
1010   Out << "Entered call";
1011   describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
1012
1013   return new PathDiagnosticEventPiece(callEnterWithin, Out.str());
1014 }
1015
1016 IntrusiveRefCntPtr<PathDiagnosticEventPiece>
1017 PathDiagnosticCallPiece::getCallExitEvent() const {
1018   if (NoExit)
1019     return nullptr;
1020
1021   SmallString<256> buf;
1022   llvm::raw_svector_ostream Out(buf);
1023
1024   if (!CallStackMessage.empty()) {
1025     Out << CallStackMessage;
1026   } else {
1027     bool DidDescribe = describeCodeDecl(Out, Callee,
1028                                         /*ExtendedDescription=*/false,
1029                                         "Returning from ");
1030     if (!DidDescribe)
1031       Out << "Returning to caller";
1032   }
1033
1034   assert(callReturn.asLocation().isValid());
1035   return new PathDiagnosticEventPiece(callReturn, Out.str());
1036 }
1037
1038 static void compute_path_size(const PathPieces &pieces, unsigned &size) {
1039   for (PathPieces::const_iterator it = pieces.begin(),
1040                                   et = pieces.end(); it != et; ++it) {
1041     const PathDiagnosticPiece *piece = it->get();
1042     if (const PathDiagnosticCallPiece *cp =
1043         dyn_cast<PathDiagnosticCallPiece>(piece)) {
1044       compute_path_size(cp->path, size);
1045     }
1046     else
1047       ++size;
1048   }
1049 }
1050
1051 unsigned PathDiagnostic::full_size() {
1052   unsigned size = 0;
1053   compute_path_size(path, size);
1054   return size;
1055 }
1056
1057 //===----------------------------------------------------------------------===//
1058 // FoldingSet profiling methods.
1059 //===----------------------------------------------------------------------===//
1060
1061 void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
1062   ID.AddInteger(Range.getBegin().getRawEncoding());
1063   ID.AddInteger(Range.getEnd().getRawEncoding());
1064   ID.AddInteger(Loc.getRawEncoding());
1065   return;
1066 }
1067
1068 void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1069   ID.AddInteger((unsigned) getKind());
1070   ID.AddString(str);
1071   // FIXME: Add profiling support for code hints.
1072   ID.AddInteger((unsigned) getDisplayHint());
1073   ArrayRef<SourceRange> Ranges = getRanges();
1074   for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
1075                                         I != E; ++I) {
1076     ID.AddInteger(I->getBegin().getRawEncoding());
1077     ID.AddInteger(I->getEnd().getRawEncoding());
1078   }
1079 }
1080
1081 void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1082   PathDiagnosticPiece::Profile(ID);
1083   for (PathPieces::const_iterator it = path.begin(),
1084        et = path.end(); it != et; ++it) {
1085     ID.Add(**it);
1086   }
1087 }
1088
1089 void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1090   PathDiagnosticPiece::Profile(ID);
1091   ID.Add(Pos);
1092 }
1093
1094 void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1095   PathDiagnosticPiece::Profile(ID);
1096   for (const_iterator I = begin(), E = end(); I != E; ++I)
1097     ID.Add(*I);
1098 }
1099
1100 void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1101   PathDiagnosticSpotPiece::Profile(ID);
1102   for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end();
1103        I != E; ++I)
1104     ID.Add(**I);
1105 }
1106
1107 void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
1108   ID.Add(getLocation());
1109   ID.AddString(BugType);
1110   ID.AddString(VerboseDesc);
1111   ID.AddString(Category);
1112 }
1113
1114 void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1115   Profile(ID);
1116   for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E; ++I)
1117     ID.Add(**I);
1118   for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1119     ID.AddString(*I);
1120 }
1121
1122 StackHintGenerator::~StackHintGenerator() {}
1123
1124 std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){
1125   ProgramPoint P = N->getLocation();
1126   CallExitEnd CExit = P.castAs<CallExitEnd>();
1127
1128   // FIXME: Use CallEvent to abstract this over all calls.
1129   const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
1130   const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite);
1131   if (!CE)
1132     return "";
1133
1134   if (!N)
1135     return getMessageForSymbolNotFound();
1136
1137   // Check if one of the parameters are set to the interesting symbol.
1138   ProgramStateRef State = N->getState();
1139   const LocationContext *LCtx = N->getLocationContext();
1140   unsigned ArgIndex = 0;
1141   for (CallExpr::const_arg_iterator I = CE->arg_begin(),
1142                                     E = CE->arg_end(); I != E; ++I, ++ArgIndex){
1143     SVal SV = State->getSVal(*I, LCtx);
1144
1145     // Check if the variable corresponding to the symbol is passed by value.
1146     SymbolRef AS = SV.getAsLocSymbol();
1147     if (AS == Sym) {
1148       return getMessageForArg(*I, ArgIndex);
1149     }
1150
1151     // Check if the parameter is a pointer to the symbol.
1152     if (Optional<loc::MemRegionVal> Reg = SV.getAs<loc::MemRegionVal>()) {
1153       SVal PSV = State->getSVal(Reg->getRegion());
1154       SymbolRef AS = PSV.getAsLocSymbol();
1155       if (AS == Sym) {
1156         return getMessageForArg(*I, ArgIndex);
1157       }
1158     }
1159   }
1160
1161   // Check if we are returning the interesting symbol.
1162   SVal SV = State->getSVal(CE, LCtx);
1163   SymbolRef RetSym = SV.getAsLocSymbol();
1164   if (RetSym == Sym) {
1165     return getMessageForReturn(CE);
1166   }
1167
1168   return getMessageForSymbolNotFound();
1169 }
1170
1171 std::string StackHintGeneratorForSymbol::getMessageForArg(const Expr *ArgE,
1172                                                           unsigned ArgIndex) {
1173   // Printed parameters start at 1, not 0.
1174   ++ArgIndex;
1175
1176   SmallString<200> buf;
1177   llvm::raw_svector_ostream os(buf);
1178
1179   os << Msg << " via " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1180      << " parameter";
1181
1182   return os.str();
1183 }