1 //===--- PlistDiagnostics.cpp - Plist Diagnostics for Paths -----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //  This file defines the PlistDiagnostics object.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/Basic/FileManager.h"
14 #include "clang/Basic/PlistSupport.h"
15 #include "clang/Basic/SourceManager.h"
16 #include "clang/Basic/Version.h"
17 #include "clang/Lex/Preprocessor.h"
18 #include "clang/Lex/TokenConcatenation.h"
19 #include "clang/Rewrite/Core/HTMLRewrite.h"
20 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
21 #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
22 #include "clang/StaticAnalyzer/Core/IssueHash.h"
23 #include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
24 #include "llvm/ADT/Statistic.h"
25 #include "llvm/ADT/SmallVector.h"
26 #include "llvm/Support/Casting.h"
27 
28 using namespace clang;
29 using namespace ento;
30 using namespace markup;
31 
32 //===----------------------------------------------------------------------===//
33 // Declarations of helper classes and functions for emitting bug reports in
34 // plist format.
35 //===----------------------------------------------------------------------===//
36 
37 namespace {
38   class PlistDiagnostics : public PathDiagnosticConsumer {
39     const std::string OutputFile;
40     const Preprocessor &PP;
41     AnalyzerOptions &AnOpts;
42     const bool SupportsCrossFileDiagnostics;
43   public:
44     PlistDiagnostics(AnalyzerOptions &AnalyzerOpts,
45                      const std::string& prefix,
46                      const Preprocessor &PP,
47                      bool supportsMultipleFiles);
48 
49     ~PlistDiagnostics() override {}
50 
51     void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
52                               FilesMade *filesMade) override;
53 
54     StringRef getName() const override {
55       return "PlistDiagnostics";
56     }
57 
58     PathGenerationScheme getGenerationScheme() const override {
59       return Extensive;
60     }
61     bool supportsLogicalOpControlFlow() const override { return true; }
62     bool supportsCrossFileDiagnostics() const override {
63       return SupportsCrossFileDiagnostics;
64     }
65   };
66 } // end anonymous namespace
67 
68 namespace {
69 
70 /// A helper class for emitting a single report.
71 class PlistPrinter {
72   const FIDMap& FM;
73   AnalyzerOptions &AnOpts;
74   const Preprocessor &PP;
75   llvm::SmallVector<const PathDiagnosticMacroPiece *, 0> MacroPieces;
76 
77 public:
78   PlistPrinter(const FIDMap& FM, AnalyzerOptions &AnOpts,
79                const Preprocessor &PP)
80     : FM(FM), AnOpts(AnOpts), PP(PP) {
81   }
82 
83   void ReportDiag(raw_ostream &o, const PathDiagnosticPiece& P) {
84     ReportPiece(o, P, /*indent*/ 4, /*depth*/ 0, /*includeControlFlow*/ true);
85 
86     // Don't emit a warning about an unused private field.
87     (void)AnOpts;
88   }
89 
90   /// Print the expansions of the collected macro pieces.
91   ///
92   /// Each time ReportDiag is called on a PathDiagnosticMacroPiece (or, if one
93   /// is found through a call piece, etc), it's subpieces are reported, and the
94   /// piece itself is collected. Call this function after the entire bugpath
95   /// was reported.
96   void ReportMacroExpansions(raw_ostream &o, unsigned indent);
97 
98 private:
99   void ReportPiece(raw_ostream &o, const PathDiagnosticPiece &P,
100                    unsigned indent, unsigned depth, bool includeControlFlow,
101                    bool isKeyEvent = false) {
102     switch (P.getKind()) {
103       case PathDiagnosticPiece::ControlFlow:
104         if (includeControlFlow)
105           ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), indent);
106         break;
107       case PathDiagnosticPiece::Call:
108         ReportCall(o, cast<PathDiagnosticCallPiece>(P), indent,
109                    depth);
110         break;
111       case PathDiagnosticPiece::Event:
112         ReportEvent(o, cast<PathDiagnosticEventPiece>(P), indent, depth,
113                     isKeyEvent);
114         break;
115       case PathDiagnosticPiece::Macro:
116         ReportMacroSubPieces(o, cast<PathDiagnosticMacroPiece>(P), indent,
117                              depth);
118         break;
119       case PathDiagnosticPiece::Note:
120         ReportNote(o, cast<PathDiagnosticNotePiece>(P), indent);
121         break;
122     }
123   }
124 
125   void EmitRanges(raw_ostream &o, const ArrayRef<SourceRange> Ranges,
126                   unsigned indent);
127   void EmitMessage(raw_ostream &o, StringRef Message, unsigned indent);
128 
129   void ReportControlFlow(raw_ostream &o,
130                          const PathDiagnosticControlFlowPiece& P,
131                          unsigned indent);
132   void ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P,
133                    unsigned indent, unsigned depth, bool isKeyEvent = false);
134   void ReportCall(raw_ostream &o, const PathDiagnosticCallPiece &P,
135                   unsigned indent, unsigned depth);
136   void ReportMacroSubPieces(raw_ostream &o, const PathDiagnosticMacroPiece& P,
137                             unsigned indent, unsigned depth);
138   void ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P,
139                   unsigned indent);
140 };
141 
142 } // end of anonymous namespace
143 
144 namespace {
145 
146 struct ExpansionInfo {
147   std::string MacroName;
148   std::string Expansion;
149   ExpansionInfo(std::string N, std::string E)
150     : MacroName(std::move(N)), Expansion(std::move(E)) {}
151 };
152 
153 } // end of anonymous namespace
154 
155 static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
156                          AnalyzerOptions &AnOpts,
157                          const Preprocessor &PP,
158                          const PathPieces &Path);
159 
160 /// Print coverage information to output stream {@code o}.
161 /// May modify the used list of files {@code Fids} by inserting new ones.
162 static void printCoverage(const PathDiagnostic *D,
163                           unsigned InputIndentLevel,
164                           SmallVectorImpl<FileID> &Fids,
165                           FIDMap &FM,
166                           llvm::raw_fd_ostream &o);
167 
168 static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc,
169                                       const Preprocessor &PP);
170 
171 //===----------------------------------------------------------------------===//
172 // Methods of PlistPrinter.
173 //===----------------------------------------------------------------------===//
174 
175 void PlistPrinter::EmitRanges(raw_ostream &o,
176                               const ArrayRef<SourceRange> Ranges,
177                               unsigned indent) {
178 
179   if (Ranges.empty())
180     return;
181 
182   Indent(o, indent) << "<key>ranges</key>\n";
183   Indent(o, indent) << "<array>\n";
184   ++indent;
185 
186   const SourceManager &SM = PP.getSourceManager();
187   const LangOptions &LangOpts = PP.getLangOpts();
188 
189   for (auto &R : Ranges)
190     EmitRange(o, SM,
191               Lexer::getAsCharRange(SM.getExpansionRange(R), SM, LangOpts),
192               FM, indent + 1);
193   --indent;
194   Indent(o, indent) << "</array>\n";
195 }
196 
197 void PlistPrinter::EmitMessage(raw_ostream &o, StringRef Message,
198                                unsigned indent) {
199   // Output the text.
200   assert(!Message.empty());
201   Indent(o, indent) << "<key>extended_message</key>\n";
202   Indent(o, indent);
203   EmitString(o, Message) << '\n';
204 
205   // Output the short text.
206   // FIXME: Really use a short string.
207   Indent(o, indent) << "<key>message</key>\n";
208   Indent(o, indent);
209   EmitString(o, Message) << '\n';
210 }
211 
212 void PlistPrinter::ReportControlFlow(raw_ostream &o,
213                                      const PathDiagnosticControlFlowPiece& P,
214                                      unsigned indent) {
215 
216   const SourceManager &SM = PP.getSourceManager();
217   const LangOptions &LangOpts = PP.getLangOpts();
218 
219   Indent(o, indent) << "<dict>\n";
220   ++indent;
221 
222   Indent(o, indent) << "<key>kind</key><string>control</string>\n";
223 
224   // Emit edges.
225   Indent(o, indent) << "<key>edges</key>\n";
226   ++indent;
227   Indent(o, indent) << "<array>\n";
228   ++indent;
229   for (PathDiagnosticControlFlowPiece::const_iterator I=P.begin(), E=P.end();
230        I!=E; ++I) {
231     Indent(o, indent) << "<dict>\n";
232     ++indent;
233 
234     // Make the ranges of the start and end point self-consistent with adjacent edges
235     // by forcing to use only the beginning of the range.  This simplifies the layout
236     // logic for clients.
237     Indent(o, indent) << "<key>start</key>\n";
238     SourceRange StartEdge(
239         SM.getExpansionLoc(I->getStart().asRange().getBegin()));
240     EmitRange(o, SM, Lexer::getAsCharRange(StartEdge, SM, LangOpts), FM,
241               indent + 1);
242 
243     Indent(o, indent) << "<key>end</key>\n";
244     SourceRange EndEdge(SM.getExpansionLoc(I->getEnd().asRange().getBegin()));
245     EmitRange(o, SM, Lexer::getAsCharRange(EndEdge, SM, LangOpts), FM,
246               indent + 1);
247 
248     --indent;
249     Indent(o, indent) << "</dict>\n";
250   }
251   --indent;
252   Indent(o, indent) << "</array>\n";
253   --indent;
254 
255   // Output any helper text.
256   const auto &s = P.getString();
257   if (!s.empty()) {
258     Indent(o, indent) << "<key>alternate</key>";
259     EmitString(o, s) << '\n';
260   }
261 
262   --indent;
263   Indent(o, indent) << "</dict>\n";
264 }
265 
266 void PlistPrinter::ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P,
267                                unsigned indent, unsigned depth,
268                                bool isKeyEvent) {
269 
270   const SourceManager &SM = PP.getSourceManager();
271 
272   Indent(o, indent) << "<dict>\n";
273   ++indent;
274 
275   Indent(o, indent) << "<key>kind</key><string>event</string>\n";
276 
277   if (isKeyEvent) {
278     Indent(o, indent) << "<key>key_event</key><true/>\n";
279   }
280 
281   // Output the location.
282   FullSourceLoc L = P.getLocation().asLocation();
283 
284   Indent(o, indent) << "<key>location</key>\n";
285   EmitLocation(o, SM, L, FM, indent);
286 
287   // Output the ranges (if any).
288   ArrayRef<SourceRange> Ranges = P.getRanges();
289   EmitRanges(o, Ranges, indent);
290 
291   // Output the call depth.
292   Indent(o, indent) << "<key>depth</key>";
293   EmitInteger(o, depth) << '\n';
294 
295   // Output the text.
296   EmitMessage(o, P.getString(), indent);
297 
298   // Finish up.
299   --indent;
300   Indent(o, indent); o << "</dict>\n";
301 }
302 
303 void PlistPrinter::ReportCall(raw_ostream &o, const PathDiagnosticCallPiece &P,
304                               unsigned indent,
305                               unsigned depth) {
306 
307   if (auto callEnter = P.getCallEnterEvent())
308     ReportPiece(o, *callEnter, indent, depth, /*includeControlFlow*/ true,
309                 P.isLastInMainSourceFile());
310 
311 
312   ++depth;
313 
314   if (auto callEnterWithinCaller = P.getCallEnterWithinCallerEvent())
315     ReportPiece(o, *callEnterWithinCaller, indent, depth,
316                 /*includeControlFlow*/ true);
317 
318   for (PathPieces::const_iterator I = P.path.begin(), E = P.path.end();I!=E;++I)
319     ReportPiece(o, **I, indent, depth, /*includeControlFlow*/ true);
320 
321   --depth;
322 
323   if (auto callExit = P.getCallExitEvent())
324     ReportPiece(o, *callExit, indent, depth, /*includeControlFlow*/ true);
325 }
326 
327 void PlistPrinter::ReportMacroSubPieces(raw_ostream &o,
328                                         const PathDiagnosticMacroPiece& P,
329                                         unsigned indent, unsigned depth) {
330   MacroPieces.push_back(&P);
331 
332   for (PathPieces::const_iterator I = P.subPieces.begin(),
333                                   E = P.subPieces.end();
334        I != E; ++I) {
335     ReportPiece(o, **I, indent, depth, /*includeControlFlow*/ false);
336   }
337 }
338 
339 void PlistPrinter::ReportMacroExpansions(raw_ostream &o, unsigned indent) {
340 
341   for (const PathDiagnosticMacroPiece *P : MacroPieces) {
342     const SourceManager &SM = PP.getSourceManager();
343     ExpansionInfo EI = getExpandedMacro(P->getLocation().asLocation(), PP);
344 
345     Indent(o, indent) << "<dict>\n";
346     ++indent;
347 
348     // Output the location.
349     FullSourceLoc L = P->getLocation().asLocation();
350 
351     Indent(o, indent) << "<key>location</key>\n";
352     EmitLocation(o, SM, L, FM, indent);
353 
354     // Output the ranges (if any).
355     ArrayRef<SourceRange> Ranges = P->getRanges();
356     EmitRanges(o, Ranges, indent);
357 
358     // Output the macro name.
359     Indent(o, indent) << "<key>name</key>";
360     EmitString(o, EI.MacroName) << '\n';
361 
362     // Output what it expands into.
363     Indent(o, indent) << "<key>expansion</key>";
364     EmitString(o, EI.Expansion) << '\n';
365 
366     // Finish up.
367     --indent;
368     Indent(o, indent);
369     o << "</dict>\n";
370   }
371 }
372 
373 void PlistPrinter::ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P,
374                               unsigned indent) {
375 
376   const SourceManager &SM = PP.getSourceManager();
377 
378   Indent(o, indent) << "<dict>\n";
379   ++indent;
380 
381   // Output the location.
382   FullSourceLoc L = P.getLocation().asLocation();
383 
384   Indent(o, indent) << "<key>location</key>\n";
385   EmitLocation(o, SM, L, FM, indent);
386 
387   // Output the ranges (if any).
388   ArrayRef<SourceRange> Ranges = P.getRanges();
389   EmitRanges(o, Ranges, indent);
390 
391   // Output the text.
392   EmitMessage(o, P.getString(), indent);
393 
394   // Finish up.
395   --indent;
396   Indent(o, indent); o << "</dict>\n";
397 }
398 
399 //===----------------------------------------------------------------------===//
400 // Static function definitions.
401 //===----------------------------------------------------------------------===//
402 
403 /// Print coverage information to output stream {@code o}.
404 /// May modify the used list of files {@code Fids} by inserting new ones.
405 static void printCoverage(const PathDiagnostic *D,
406                           unsigned InputIndentLevel,
407                           SmallVectorImpl<FileID> &Fids,
408                           FIDMap &FM,
409                           llvm::raw_fd_ostream &o) {
410   unsigned IndentLevel = InputIndentLevel;
411 
412   Indent(o, IndentLevel) << "<key>ExecutedLines</key>\n";
413   Indent(o, IndentLevel) << "<dict>\n";
414   IndentLevel++;
415 
416   // Mapping from file IDs to executed lines.
417   const FilesToLineNumsMap &ExecutedLines = D->getExecutedLines();
418   for (auto I = ExecutedLines.begin(), E = ExecutedLines.end(); I != E; ++I) {
419     unsigned FileKey = AddFID(FM, Fids, I->first);
420     Indent(o, IndentLevel) << "<key>" << FileKey << "</key>\n";
421     Indent(o, IndentLevel) << "<array>\n";
422     IndentLevel++;
423     for (unsigned LineNo : I->second) {
424       Indent(o, IndentLevel);
425       EmitInteger(o, LineNo) << "\n";
426     }
427     IndentLevel--;
428     Indent(o, IndentLevel) << "</array>\n";
429   }
430   IndentLevel--;
431   Indent(o, IndentLevel) << "</dict>\n";
432 
433   assert(IndentLevel == InputIndentLevel);
434 }
435 
436 static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
437                          AnalyzerOptions &AnOpts,
438                          const Preprocessor &PP,
439                          const PathPieces &Path) {
440   PlistPrinter Printer(FM, AnOpts, PP);
441   assert(std::is_partitioned(
442            Path.begin(), Path.end(),
443            [](const std::shared_ptr<PathDiagnosticPiece> &E)
444              { return E->getKind() == PathDiagnosticPiece::Note; }) &&
445          "PathDiagnostic is not partitioned so that notes precede the rest");
446 
447   PathPieces::const_iterator FirstNonNote = std::partition_point(
448       Path.begin(), Path.end(),
449       [](const std::shared_ptr<PathDiagnosticPiece> &E)
450         { return E->getKind() == PathDiagnosticPiece::Note; });
451 
452   PathPieces::const_iterator I = Path.begin();
453 
454   if (FirstNonNote != Path.begin()) {
455     o << "   <key>notes</key>\n"
456          "   <array>\n";
457 
458     for (; I != FirstNonNote; ++I)
459       Printer.ReportDiag(o, **I);
460 
461     o << "   </array>\n";
462   }
463 
464   o << "   <key>path</key>\n";
465 
466   o << "   <array>\n";
467 
468   for (PathPieces::const_iterator E = Path.end(); I != E; ++I)
469     Printer.ReportDiag(o, **I);
470 
471   o << "   </array>\n";
472 
473   if (!AnOpts.ShouldDisplayMacroExpansions)
474     return;
475 
476   o << "   <key>macro_expansions</key>\n"
477        "   <array>\n";
478   Printer.ReportMacroExpansions(o, /* indent */ 4);
479   o << "   </array>\n";
480 }
481 
482 //===----------------------------------------------------------------------===//
483 // Methods of PlistDiagnostics.
484 //===----------------------------------------------------------------------===//
485 
486 PlistDiagnostics::PlistDiagnostics(AnalyzerOptions &AnalyzerOpts,
487                                    const std::string& output,
488                                    const Preprocessor &PP,
489                                    bool supportsMultipleFiles)
490   : OutputFile(output), PP(PP), AnOpts(AnalyzerOpts),
491     SupportsCrossFileDiagnostics(supportsMultipleFiles) {}
492 
493 void ento::createPlistDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
494                                          PathDiagnosticConsumers &C,
495                                          const std::string& s,
496                                          const Preprocessor &PP) {
497   C.push_back(new PlistDiagnostics(AnalyzerOpts, s, PP,
498                                    /*supportsMultipleFiles*/ false));
499 }
500 
501 void ento::createPlistMultiFileDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
502                                                   PathDiagnosticConsumers &C,
503                                                   const std::string &s,
504                                                   const Preprocessor &PP) {
505   C.push_back(new PlistDiagnostics(AnalyzerOpts, s, PP,
506                                    /*supportsMultipleFiles*/ true));
507 }
508 void PlistDiagnostics::FlushDiagnosticsImpl(
509                                     std::vector<const PathDiagnostic *> &Diags,
510                                     FilesMade *filesMade) {
511   // Build up a set of FIDs that we use by scanning the locations and
512   // ranges of the diagnostics.
513   FIDMap FM;
514   SmallVector<FileID, 10> Fids;
515   const SourceManager& SM = PP.getSourceManager();
516   const LangOptions &LangOpts = PP.getLangOpts();
517 
518   auto AddPieceFID = [&FM, &Fids, &SM](const PathDiagnosticPiece &Piece) {
519     AddFID(FM, Fids, SM, Piece.getLocation().asLocation());
520     ArrayRef<SourceRange> Ranges = Piece.getRanges();
521     for (const SourceRange &Range : Ranges) {
522       AddFID(FM, Fids, SM, Range.getBegin());
523       AddFID(FM, Fids, SM, Range.getEnd());
524     }
525   };
526 
527   for (const PathDiagnostic *D : Diags) {
528 
529     SmallVector<const PathPieces *, 5> WorkList;
530     WorkList.push_back(&D->path);
531 
532     while (!WorkList.empty()) {
533       const PathPieces &Path = *WorkList.pop_back_val();
534 
535       for (const auto &Iter : Path) {
536         const PathDiagnosticPiece &Piece = *Iter;
537         AddPieceFID(Piece);
538 
539         if (const PathDiagnosticCallPiece *Call =
540                 dyn_cast<PathDiagnosticCallPiece>(&Piece)) {
541           if (auto CallEnterWithin = Call->getCallEnterWithinCallerEvent())
542             AddPieceFID(*CallEnterWithin);
543 
544           if (auto CallEnterEvent = Call->getCallEnterEvent())
545             AddPieceFID(*CallEnterEvent);
546 
547           WorkList.push_back(&Call->path);
548         } else if (const PathDiagnosticMacroPiece *Macro =
549                        dyn_cast<PathDiagnosticMacroPiece>(&Piece)) {
550           WorkList.push_back(&Macro->subPieces);
551         }
552       }
553     }
554   }
555 
556   // Open the file.
557   std::error_code EC;
558   llvm::raw_fd_ostream o(OutputFile, EC, llvm::sys::fs::F_Text);
559   if (EC) {
560     llvm::errs() << "warning: could not create file: " << EC.message() << '\n';
561     return;
562   }
563 
564   EmitPlistHeader(o);
565 
566   // Write the root object: a <dict> containing...
567   //  - "clang_version", the string representation of clang version
568   //  - "files", an <array> mapping from FIDs to file names
569   //  - "diagnostics", an <array> containing the path diagnostics
570   o << "<dict>\n" <<
571        " <key>clang_version</key>\n";
572   EmitString(o, getClangFullVersion()) << '\n';
573   o << " <key>diagnostics</key>\n"
574        " <array>\n";
575 
576   for (std::vector<const PathDiagnostic*>::iterator DI=Diags.begin(),
577        DE = Diags.end(); DI!=DE; ++DI) {
578 
579     o << "  <dict>\n";
580 
581     const PathDiagnostic *D = *DI;
582     printBugPath(o, FM, AnOpts, PP, D->path);
583 
584     // Output the bug type and bug category.
585     o << "   <key>description</key>";
586     EmitString(o, D->getShortDescription()) << '\n';
587     o << "   <key>category</key>";
588     EmitString(o, D->getCategory()) << '\n';
589     o << "   <key>type</key>";
590     EmitString(o, D->getBugType()) << '\n';
591     o << "   <key>check_name</key>";
592     EmitString(o, D->getCheckName()) << '\n';
593 
594     o << "   <!-- This hash is experimental and going to change! -->\n";
595     o << "   <key>issue_hash_content_of_line_in_context</key>";
596     PathDiagnosticLocation UPDLoc = D->getUniqueingLoc();
597     FullSourceLoc L(SM.getExpansionLoc(UPDLoc.isValid()
598                                             ? UPDLoc.asLocation()
599                                             : D->getLocation().asLocation()),
600                     SM);
601     const Decl *DeclWithIssue = D->getDeclWithIssue();
602     EmitString(o, GetIssueHash(SM, L, D->getCheckName(), D->getBugType(),
603                                DeclWithIssue, LangOpts))
604         << '\n';
605 
606     // Output information about the semantic context where
607     // the issue occurred.
608     if (const Decl *DeclWithIssue = D->getDeclWithIssue()) {
609       // FIXME: handle blocks, which have no name.
610       if (const NamedDecl *ND = dyn_cast<NamedDecl>(DeclWithIssue)) {
611         StringRef declKind;
612         switch (ND->getKind()) {
613           case Decl::CXXRecord:
614             declKind = "C++ class";
615             break;
616           case Decl::CXXMethod:
617             declKind = "C++ method";
618             break;
619           case Decl::ObjCMethod:
620             declKind = "Objective-C method";
621             break;
622           case Decl::Function:
623             declKind = "function";
624             break;
625           default:
626             break;
627         }
628         if (!declKind.empty()) {
629           const std::string &declName = ND->getDeclName().getAsString();
630           o << "  <key>issue_context_kind</key>";
631           EmitString(o, declKind) << '\n';
632           o << "  <key>issue_context</key>";
633           EmitString(o, declName) << '\n';
634         }
635 
636         // Output the bug hash for issue unique-ing. Currently, it's just an
637         // offset from the beginning of the function.
638         if (const Stmt *Body = DeclWithIssue->getBody()) {
639 
640           // If the bug uniqueing location exists, use it for the hash.
641           // For example, this ensures that two leaks reported on the same line
642           // will have different issue_hashes and that the hash will identify
643           // the leak location even after code is added between the allocation
644           // site and the end of scope (leak report location).
645           if (UPDLoc.isValid()) {
646             FullSourceLoc UFunL(
647                 SM.getExpansionLoc(
648                     D->getUniqueingDecl()->getBody()->getBeginLoc()),
649                 SM);
650             o << "  <key>issue_hash_function_offset</key><string>"
651               << L.getExpansionLineNumber() - UFunL.getExpansionLineNumber()
652               << "</string>\n";
653 
654           // Otherwise, use the location on which the bug is reported.
655           } else {
656             FullSourceLoc FunL(SM.getExpansionLoc(Body->getBeginLoc()), SM);
657             o << "  <key>issue_hash_function_offset</key><string>"
658               << L.getExpansionLineNumber() - FunL.getExpansionLineNumber()
659               << "</string>\n";
660           }
661 
662         }
663       }
664     }
665 
666     // Output the location of the bug.
667     o << "  <key>location</key>\n";
668     EmitLocation(o, SM, D->getLocation().asLocation(), FM, 2);
669 
670     // Output the diagnostic to the sub-diagnostic client, if any.
671     if (!filesMade->empty()) {
672       StringRef lastName;
673       PDFileEntry::ConsumerFiles *files = filesMade->getFiles(*D);
674       if (files) {
675         for (PDFileEntry::ConsumerFiles::const_iterator CI = files->begin(),
676                 CE = files->end(); CI != CE; ++CI) {
677           StringRef newName = CI->first;
678           if (newName != lastName) {
679             if (!lastName.empty()) {
680               o << "  </array>\n";
681             }
682             lastName = newName;
683             o <<  "  <key>" << lastName << "_files</key>\n";
684             o << "  <array>\n";
685           }
686           o << "   <string>" << CI->second << "</string>\n";
687         }
688         o << "  </array>\n";
689       }
690     }
691 
692     printCoverage(D, /*IndentLevel=*/2, Fids, FM, o);
693 
694     // Close up the entry.
695     o << "  </dict>\n";
696   }
697 
698   o << " </array>\n";
699 
700   o << " <key>files</key>\n"
701        " <array>\n";
702   for (FileID FID : Fids)
703     EmitString(o << "  ", SM.getFileEntryForID(FID)->getName()) << '\n';
704   o << " </array>\n";
705 
706   if (llvm::AreStatisticsEnabled() && AnOpts.ShouldSerializeStats) {
707     o << " <key>statistics</key>\n";
708     std::string stats;
709     llvm::raw_string_ostream os(stats);
710     llvm::PrintStatisticsJSON(os);
711     os.flush();
712     EmitString(o, html::EscapeText(stats)) << '\n';
713   }
714 
715   // Finish.
716   o << "</dict>\n</plist>";
717 }
718 
719 //===----------------------------------------------------------------------===//
720 // Declarations of helper functions and data structures for expanding macros.
721 //===----------------------------------------------------------------------===//
722 
723 namespace {
724 
725 using ExpArgTokens = llvm::SmallVector<Token, 2>;
726 
727 /// Maps unexpanded macro arguments to expanded arguments. A macro argument may
728 /// need to expanded further when it is nested inside another macro.
729 class MacroArgMap : public std::map<const IdentifierInfo *, ExpArgTokens> {
730 public:
731   void expandFromPrevMacro(const MacroArgMap &Super);
732 };
733 
734 struct MacroNameAndArgs {
735   std::string Name;
736   const MacroInfo *MI = nullptr;
737   MacroArgMap Args;
738 
739   MacroNameAndArgs(std::string N, const MacroInfo *MI, MacroArgMap M)
740     : Name(std::move(N)), MI(MI), Args(std::move(M)) {}
741 };
742 
743 class TokenPrinter {
744   llvm::raw_ostream &OS;
745   const Preprocessor &PP;
746 
747   Token PrevTok, PrevPrevTok;
748   TokenConcatenation ConcatInfo;
749 
750 public:
751   TokenPrinter(llvm::raw_ostream &OS, const Preprocessor &PP)
752     : OS(OS), PP(PP), ConcatInfo(PP) {
753     PrevTok.setKind(tok::unknown);
754     PrevPrevTok.setKind(tok::unknown);
755   }
756 
757   void printToken(const Token &Tok);
758 };
759 
760 } // end of anonymous namespace
761 
762 /// The implementation method of getMacroExpansion: It prints the expansion of
763 /// a macro to \p Printer, and returns with the name of the macro.
764 ///
765 /// Since macros can be nested in one another, this function may call itself
766 /// recursively.
767 ///
768 /// Unfortunately, macro arguments have to expanded manually. To understand why,
769 /// observe the following example:
770 ///
771 ///   #define PRINT(x) print(x)
772 ///   #define DO_SOMETHING(str) PRINT(str)
773 ///
774 ///   DO_SOMETHING("Cute panda cubs.");
775 ///
776 /// As we expand the last line, we'll immediately replace PRINT(str) with
777 /// print(x). The information that both 'str' and 'x' refers to the same string
778 /// is an information we have to forward, hence the argument \p PrevArgs.
779 static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer,
780                                                  SourceLocation MacroLoc,
781                                                  const Preprocessor &PP,
782                                                  const MacroArgMap &PrevArgs);
783 
784 /// Retrieves the name of the macro and what it's arguments expand into
785 /// at \p ExpanLoc.
786 ///
787 /// For example, for the following macro expansion:
788 ///
789 ///   #define SET_TO_NULL(x) x = 0
790 ///   #define NOT_SUSPICIOUS(a) \
791 ///     {                       \
792 ///       int b = 0;            \
793 ///     }                       \
794 ///     SET_TO_NULL(a)
795 ///
796 ///   int *ptr = new int(4);
797 ///   NOT_SUSPICIOUS(&ptr);
798 ///   *ptr = 5;
799 ///
800 /// When \p ExpanLoc references the last line, the macro name "NOT_SUSPICIOUS"
801 /// and the MacroArgMap map { (a, &ptr) } will be returned.
802 ///
803 /// When \p ExpanLoc references "SET_TO_NULL(a)" within the definition of
804 /// "NOT_SUSPICOUS", the macro name "SET_TO_NULL" and the MacroArgMap map
805 /// { (x, a) } will be returned.
806 static MacroNameAndArgs getMacroNameAndArgs(SourceLocation ExpanLoc,
807                                             const Preprocessor &PP);
808 
809 /// Retrieves the ')' token that matches '(' \p It points to.
810 static MacroInfo::tokens_iterator getMatchingRParen(
811     MacroInfo::tokens_iterator It,
812     MacroInfo::tokens_iterator End);
813 
814 /// Retrieves the macro info for \p II refers to at \p Loc. This is important
815 /// because macros can be redefined or undefined.
816 static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP,
817                                                 const SourceManager &SM,
818                                                 const IdentifierInfo *II,
819                                                 SourceLocation Loc);
820 
821 //===----------------------------------------------------------------------===//
822 // Definitions of helper functions and methods for expanding macros.
823 //===----------------------------------------------------------------------===//
824 
825 static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc,
826                                       const Preprocessor &PP) {
827 
828   llvm::SmallString<200> ExpansionBuf;
829   llvm::raw_svector_ostream OS(ExpansionBuf);
830   TokenPrinter Printer(OS, PP);
831   std::string MacroName =
832             getMacroNameAndPrintExpansion(Printer, MacroLoc, PP, MacroArgMap{});
833   return { MacroName, OS.str() };
834 }
835 
836 static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer,
837                                                  SourceLocation MacroLoc,
838                                                  const Preprocessor &PP,
839                                                  const MacroArgMap &PrevArgs) {
840 
841   const SourceManager &SM = PP.getSourceManager();
842 
843   MacroNameAndArgs Info = getMacroNameAndArgs(SM.getExpansionLoc(MacroLoc), PP);
844 
845   // Manually expand its arguments from the previous macro.
846   Info.Args.expandFromPrevMacro(PrevArgs);
847 
848   // Iterate over the macro's tokens and stringify them.
849   for (auto It = Info.MI->tokens_begin(), E = Info.MI->tokens_end(); It != E;
850        ++It) {
851     Token T = *It;
852 
853     // If this token is not an identifier, we only need to print it.
854     if (T.isNot(tok::identifier)) {
855       Printer.printToken(T);
856       continue;
857     }
858 
859     const auto *II = T.getIdentifierInfo();
860     assert(II &&
861           "This token is an identifier but has no IdentifierInfo!");
862 
863     // If this token is a macro that should be expanded inside the current
864     // macro.
865     if (const MacroInfo *MI =
866                          getMacroInfoForLocation(PP, SM, II, T.getLocation())) {
867       getMacroNameAndPrintExpansion(Printer, T.getLocation(), PP, Info.Args);
868 
869       // If this is a function-like macro, skip its arguments, as
870       // getExpandedMacro() already printed them. If this is the case, let's
871       // first jump to the '(' token.
872       if (MI->getNumParams() != 0)
873         It = getMatchingRParen(++It, E);
874       continue;
875     }
876 
877     // If this token is the current macro's argument, we should expand it.
878     auto ArgMapIt = Info.Args.find(II);
879     if (ArgMapIt != Info.Args.end()) {
880       for (MacroInfo::tokens_iterator ArgIt = ArgMapIt->second.begin(),
881                                       ArgEnd = ArgMapIt->second.end();
882            ArgIt != ArgEnd; ++ArgIt) {
883 
884         // These tokens may still be macros, if that is the case, handle it the
885         // same way we did above.
886         const auto *ArgII = ArgIt->getIdentifierInfo();
887         if (!ArgII) {
888           Printer.printToken(*ArgIt);
889           continue;
890         }
891 
892         const auto *MI = PP.getMacroInfo(ArgII);
893         if (!MI) {
894           Printer.printToken(*ArgIt);
895           continue;
896         }
897 
898         getMacroNameAndPrintExpansion(Printer, ArgIt->getLocation(), PP,
899                                       Info.Args);
900         if (MI->getNumParams() != 0)
901           ArgIt = getMatchingRParen(++ArgIt, ArgEnd);
902       }
903       continue;
904     }
905 
906     // If control reached here, then this token isn't a macro identifier, nor an
907     // unexpanded macro argument that we need to handle, print it.
908     Printer.printToken(T);
909   }
910 
911   return Info.Name;
912 }
913 
914 static MacroNameAndArgs getMacroNameAndArgs(SourceLocation ExpanLoc,
915                                             const Preprocessor &PP) {
916 
917   const SourceManager &SM = PP.getSourceManager();
918   const LangOptions &LangOpts = PP.getLangOpts();
919 
920   // First, we create a Lexer to lex *at the expansion location* the tokens
921   // referring to the macro's name and its arguments.
922   std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(ExpanLoc);
923   const llvm::MemoryBuffer *MB = SM.getBuffer(LocInfo.first);
924   const char *MacroNameTokenPos = MB->getBufferStart() + LocInfo.second;
925 
926   Lexer RawLexer(SM.getLocForStartOfFile(LocInfo.first), LangOpts,
927                  MB->getBufferStart(), MacroNameTokenPos, MB->getBufferEnd());
928 
929   // Acquire the macro's name.
930   Token TheTok;
931   RawLexer.LexFromRawLexer(TheTok);
932 
933   std::string MacroName = PP.getSpelling(TheTok);
934 
935   const auto *II = PP.getIdentifierInfo(MacroName);
936   assert(II && "Failed to acquire the IndetifierInfo for the macro!");
937 
938   const MacroInfo *MI = getMacroInfoForLocation(PP, SM, II, ExpanLoc);
939   assert(MI && "The macro must've been defined at it's expansion location!");
940 
941   // Acquire the macro's arguments.
942   //
943   // The rough idea here is to lex from the first left parentheses to the last
944   // right parentheses, and map the macro's unexpanded arguments to what they
945   // will be expanded to. An expanded macro argument may contain several tokens
946   // (like '3 + 4'), so we'll lex until we find a tok::comma or tok::r_paren, at
947   // which point we start lexing the next argument or finish.
948   ArrayRef<const IdentifierInfo *> MacroArgs = MI->params();
949   if (MacroArgs.empty())
950     return { MacroName, MI, {} };
951 
952   RawLexer.LexFromRawLexer(TheTok);
953   assert(TheTok.is(tok::l_paren) &&
954          "The token after the macro's identifier token should be '('!");
955 
956   MacroArgMap Args;
957 
958   // When the macro's argument is a function call, like
959   //   CALL_FN(someFunctionName(param1, param2))
960   // we will find tok::l_paren, tok::r_paren, and tok::comma that do not divide
961   // actual macro arguments, or do not represent the macro argument's closing
962   // parentheses, so we'll count how many parentheses aren't closed yet.
963   // If ParanthesesDepth
964   //   * = 0, then there are no more arguments to lex.
965   //   * = 1, then if we find a tok::comma, we can start lexing the next arg.
966   //   * > 1, then tok::comma is a part of the current arg.
967   int ParenthesesDepth = 1;
968 
969   // If we encounter __VA_ARGS__, we will lex until the closing tok::r_paren,
970   // even if we lex a tok::comma and ParanthesesDepth == 1.
971   const IdentifierInfo *__VA_ARGS__II = PP.getIdentifierInfo("__VA_ARGS__");
972 
973   for (const IdentifierInfo *UnexpArgII : MacroArgs) {
974     MacroArgMap::mapped_type ExpandedArgTokens;
975 
976     // One could also simply not supply a single argument to __VA_ARGS__ -- this
977     // results in a preprocessor warning, but is not an error:
978     //   #define VARIADIC(ptr, ...) \
979     //     someVariadicTemplateFunction(__VA_ARGS__)
980     //
981     //   int *ptr;
982     //   VARIADIC(ptr); // Note that there are no commas, this isn't just an
983     //                  // empty parameter -- there are no parameters for '...'.
984     // In any other case, ParenthesesDepth mustn't be 0 here.
985     if (ParenthesesDepth != 0) {
986 
987       // Lex the first token of the next macro parameter.
988       RawLexer.LexFromRawLexer(TheTok);
989 
990       while (!(ParenthesesDepth == 1 &&
991               (UnexpArgII == __VA_ARGS__II ? false : TheTok.is(tok::comma)))) {
992         assert(TheTok.isNot(tok::eof) &&
993                "EOF encountered while looking for expanded macro args!");
994 
995         if (TheTok.is(tok::l_paren))
996           ++ParenthesesDepth;
997 
998         if (TheTok.is(tok::r_paren))
999           --ParenthesesDepth;
1000 
1001         if (ParenthesesDepth == 0)
1002           break;
1003 
1004         if (TheTok.is(tok::raw_identifier))
1005           PP.LookUpIdentifierInfo(TheTok);
1006 
1007         ExpandedArgTokens.push_back(TheTok);
1008         RawLexer.LexFromRawLexer(TheTok);
1009       }
1010     } else {
1011       assert(UnexpArgII == __VA_ARGS__II);
1012     }
1013 
1014     Args.emplace(UnexpArgII, std::move(ExpandedArgTokens));
1015   }
1016 
1017   assert(TheTok.is(tok::r_paren) &&
1018          "Expanded macro argument acquisition failed! After the end of the loop"
1019          " this token should be ')'!");
1020 
1021   return { MacroName, MI, Args };
1022 }
1023 
1024 static MacroInfo::tokens_iterator getMatchingRParen(
1025     MacroInfo::tokens_iterator It,
1026     MacroInfo::tokens_iterator End) {
1027 
1028   assert(It->is(tok::l_paren) && "This token should be '('!");
1029 
1030   // Skip until we find the closing ')'.
1031   int ParenthesesDepth = 1;
1032   while (ParenthesesDepth != 0) {
1033     ++It;
1034 
1035     assert(It->isNot(tok::eof) &&
1036            "Encountered EOF while attempting to skip macro arguments!");
1037     assert(It != End &&
1038            "End of the macro definition reached before finding ')'!");
1039 
1040     if (It->is(tok::l_paren))
1041       ++ParenthesesDepth;
1042 
1043     if (It->is(tok::r_paren))
1044       --ParenthesesDepth;
1045   }
1046   return It;
1047 }
1048 
1049 static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP,
1050                                                 const SourceManager &SM,
1051                                                 const IdentifierInfo *II,
1052                                                 SourceLocation Loc) {
1053 
1054   const MacroDirective *MD = PP.getLocalMacroDirectiveHistory(II);
1055   if (!MD)
1056     return nullptr;
1057 
1058   return MD->findDirectiveAtLoc(Loc, SM).getMacroInfo();
1059 }
1060 
1061 void MacroArgMap::expandFromPrevMacro(const MacroArgMap &Super) {
1062 
1063   for (value_type &Pair : *this) {
1064     ExpArgTokens &CurrExpArgTokens = Pair.second;
1065 
1066     // For each token in the expanded macro argument.
1067     auto It = CurrExpArgTokens.begin();
1068     while (It != CurrExpArgTokens.end()) {
1069       if (It->isNot(tok::identifier)) {
1070         ++It;
1071         continue;
1072       }
1073 
1074       const auto *II = It->getIdentifierInfo();
1075       assert(II);
1076 
1077       // Is this an argument that "Super" expands further?
1078       if (!Super.count(II)) {
1079         ++It;
1080         continue;
1081       }
1082 
1083       const ExpArgTokens &SuperExpArgTokens = Super.at(II);
1084 
1085       It = CurrExpArgTokens.insert(
1086           It, SuperExpArgTokens.begin(), SuperExpArgTokens.end());
1087       std::advance(It, SuperExpArgTokens.size());
1088       It = CurrExpArgTokens.erase(It);
1089     }
1090   }
1091 }
1092 
1093 void TokenPrinter::printToken(const Token &Tok) {
1094   // If this is the first token to be printed, don't print space.
1095   if (PrevTok.isNot(tok::unknown)) {
1096     // If the tokens were already space separated, or if they must be to avoid
1097     // them being implicitly pasted, add a space between them.
1098     if(Tok.hasLeadingSpace() || ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok,
1099                                                        Tok)) {
1100       // AvoidConcat doesn't check for ##, don't print a space around it.
1101       if (PrevTok.isNot(tok::hashhash) && Tok.isNot(tok::hashhash)) {
1102         OS << ' ';
1103       }
1104     }
1105   }
1106 
1107   if (!Tok.isOneOf(tok::hash, tok::hashhash)) {
1108     if (PrevTok.is(tok::hash))
1109       OS << '\"' << PP.getSpelling(Tok) << '\"';
1110     else
1111       OS << PP.getSpelling(Tok);
1112   }
1113 
1114   PrevPrevTok = PrevTok;
1115   PrevTok = Tok;
1116 }
1117