Clang Project

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