Coverage Report

Created: 2020-09-19 12:23

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