Merge branch 'addmainunit4-altlink-sharedstmt-dieref-dwz3-inlinebug-testcategory...
[lldb.git] / clang-tools-extra / pp-trace / PPCallbacksTracker.cpp
1 //===--- PPCallbacksTracker.cpp - Preprocessor tracker -*--*---------------===//
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 /// \file
10 /// Implementations for preprocessor tracking.
11 ///
12 /// See the header for details.
13 ///
14 //===----------------------------------------------------------------------===//
15
16 #include "PPCallbacksTracker.h"
17 #include "clang/Basic/FileManager.h"
18 #include "clang/Lex/MacroArgs.h"
19 #include "llvm/Support/raw_ostream.h"
20
21 namespace clang {
22 namespace pp_trace {
23
24 // Get a "file:line:column" source location string.
25 static std::string getSourceLocationString(Preprocessor &PP,
26                                            SourceLocation Loc) {
27   if (Loc.isInvalid())
28     return std::string("(none)");
29
30   if (Loc.isFileID()) {
31     PresumedLoc PLoc = PP.getSourceManager().getPresumedLoc(Loc);
32
33     if (PLoc.isInvalid()) {
34       return std::string("(invalid)");
35     }
36
37     std::string Str;
38     llvm::raw_string_ostream SS(Str);
39
40     // The macro expansion and spelling pos is identical for file locs.
41     SS << "\"" << PLoc.getFilename() << ':' << PLoc.getLine() << ':'
42        << PLoc.getColumn() << "\"";
43
44     std::string Result = SS.str();
45
46     // YAML treats backslash as escape, so use forward slashes.
47     std::replace(Result.begin(), Result.end(), '\\', '/');
48
49     return Result;
50   }
51
52   return std::string("(nonfile)");
53 }
54
55 // Enum string tables.
56
57 // FileChangeReason strings.
58 static const char *const FileChangeReasonStrings[] = {
59   "EnterFile", "ExitFile", "SystemHeaderPragma", "RenameFile"
60 };
61
62 // CharacteristicKind strings.
63 static const char *const CharacteristicKindStrings[] = { "C_User", "C_System",
64                                                          "C_ExternCSystem" };
65
66 // MacroDirective::Kind strings.
67 static const char *const MacroDirectiveKindStrings[] = {
68   "MD_Define","MD_Undefine", "MD_Visibility"
69 };
70
71 // PragmaIntroducerKind strings.
72 static const char *const PragmaIntroducerKindStrings[] = { "PIK_HashPragma",
73                                                            "PIK__Pragma",
74                                                            "PIK___pragma" };
75
76 // PragmaMessageKind strings.
77 static const char *const PragmaMessageKindStrings[] = {
78   "PMK_Message", "PMK_Warning", "PMK_Error"
79 };
80
81 // ConditionValueKind strings.
82 static const char *const ConditionValueKindStrings[] = {
83   "CVK_NotEvaluated", "CVK_False", "CVK_True"
84 };
85
86 // Mapping strings.
87 static const char *const MappingStrings[] = { "0",          "MAP_IGNORE",
88                                               "MAP_REMARK", "MAP_WARNING",
89                                               "MAP_ERROR",  "MAP_FATAL" };
90
91 // PPCallbacksTracker functions.
92
93 PPCallbacksTracker::PPCallbacksTracker(const FilterType &Filters,
94                                        std::vector<CallbackCall> &CallbackCalls,
95                                        Preprocessor &PP)
96     : CallbackCalls(CallbackCalls), Filters(Filters), PP(PP) {}
97
98 PPCallbacksTracker::~PPCallbacksTracker() {}
99
100 // Callback functions.
101
102 // Callback invoked whenever a source file is entered or exited.
103 void PPCallbacksTracker::FileChanged(SourceLocation Loc,
104                                      PPCallbacks::FileChangeReason Reason,
105                                      SrcMgr::CharacteristicKind FileType,
106                                      FileID PrevFID) {
107   beginCallback("FileChanged");
108   appendArgument("Loc", Loc);
109   appendArgument("Reason", Reason, FileChangeReasonStrings);
110   appendArgument("FileType", FileType, CharacteristicKindStrings);
111   appendArgument("PrevFID", PrevFID);
112 }
113
114 // Callback invoked whenever a source file is skipped as the result
115 // of header guard optimization.
116 void PPCallbacksTracker::FileSkipped(const FileEntryRef &SkippedFile,
117                                      const Token &FilenameTok,
118                                      SrcMgr::CharacteristicKind FileType) {
119   beginCallback("FileSkipped");
120   appendArgument("ParentFile", &SkippedFile.getFileEntry());
121   appendArgument("FilenameTok", FilenameTok);
122   appendArgument("FileType", FileType, CharacteristicKindStrings);
123 }
124
125 // Callback invoked whenever an inclusion directive results in a
126 // file-not-found error.
127 bool
128 PPCallbacksTracker::FileNotFound(llvm::StringRef FileName,
129                                  llvm::SmallVectorImpl<char> &RecoveryPath) {
130   beginCallback("FileNotFound");
131   appendFilePathArgument("FileName", FileName);
132   return false;
133 }
134
135 // Callback invoked whenever an inclusion directive of
136 // any kind (#include, #import, etc.) has been processed, regardless
137 // of whether the inclusion will actually result in an inclusion.
138 void PPCallbacksTracker::InclusionDirective(
139     SourceLocation HashLoc, const Token &IncludeTok, llvm::StringRef FileName,
140     bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
141     llvm::StringRef SearchPath, llvm::StringRef RelativePath,
142     const Module *Imported, SrcMgr::CharacteristicKind FileType) {
143   beginCallback("InclusionDirective");
144   appendArgument("IncludeTok", IncludeTok);
145   appendFilePathArgument("FileName", FileName);
146   appendArgument("IsAngled", IsAngled);
147   appendArgument("FilenameRange", FilenameRange);
148   appendArgument("File", File);
149   appendFilePathArgument("SearchPath", SearchPath);
150   appendFilePathArgument("RelativePath", RelativePath);
151   appendArgument("Imported", Imported);
152 }
153
154 // Callback invoked whenever there was an explicit module-import
155 // syntax.
156 void PPCallbacksTracker::moduleImport(SourceLocation ImportLoc,
157                                       ModuleIdPath Path,
158                                       const Module *Imported) {
159   beginCallback("moduleImport");
160   appendArgument("ImportLoc", ImportLoc);
161   appendArgument("Path", Path);
162   appendArgument("Imported", Imported);
163 }
164
165 // Callback invoked when the end of the main file is reached.
166 // No subsequent callbacks will be made.
167 void PPCallbacksTracker::EndOfMainFile() { beginCallback("EndOfMainFile"); }
168
169 // Callback invoked when a #ident or #sccs directive is read.
170 void PPCallbacksTracker::Ident(SourceLocation Loc, llvm::StringRef Str) {
171   beginCallback("Ident");
172   appendArgument("Loc", Loc);
173   appendArgument("Str", Str);
174 }
175
176 // Callback invoked when start reading any pragma directive.
177 void PPCallbacksTracker::PragmaDirective(SourceLocation Loc,
178                                          PragmaIntroducerKind Introducer) {
179   beginCallback("PragmaDirective");
180   appendArgument("Loc", Loc);
181   appendArgument("Introducer", Introducer, PragmaIntroducerKindStrings);
182 }
183
184 // Callback invoked when a #pragma comment directive is read.
185 void PPCallbacksTracker::PragmaComment(SourceLocation Loc,
186                                        const IdentifierInfo *Kind,
187                                        llvm::StringRef Str) {
188   beginCallback("PragmaComment");
189   appendArgument("Loc", Loc);
190   appendArgument("Kind", Kind);
191   appendArgument("Str", Str);
192 }
193
194 // Callback invoked when a #pragma detect_mismatch directive is
195 // read.
196 void PPCallbacksTracker::PragmaDetectMismatch(SourceLocation Loc,
197                                               llvm::StringRef Name,
198                                               llvm::StringRef Value) {
199   beginCallback("PragmaDetectMismatch");
200   appendArgument("Loc", Loc);
201   appendArgument("Name", Name);
202   appendArgument("Value", Value);
203 }
204
205 // Callback invoked when a #pragma clang __debug directive is read.
206 void PPCallbacksTracker::PragmaDebug(SourceLocation Loc,
207                                      llvm::StringRef DebugType) {
208   beginCallback("PragmaDebug");
209   appendArgument("Loc", Loc);
210   appendArgument("DebugType", DebugType);
211 }
212
213 // Callback invoked when a #pragma message directive is read.
214 void PPCallbacksTracker::PragmaMessage(SourceLocation Loc,
215                                        llvm::StringRef Namespace,
216                                        PPCallbacks::PragmaMessageKind Kind,
217                                        llvm::StringRef Str) {
218   beginCallback("PragmaMessage");
219   appendArgument("Loc", Loc);
220   appendArgument("Namespace", Namespace);
221   appendArgument("Kind", Kind, PragmaMessageKindStrings);
222   appendArgument("Str", Str);
223 }
224
225 // Callback invoked when a #pragma gcc diagnostic push directive
226 // is read.
227 void PPCallbacksTracker::PragmaDiagnosticPush(SourceLocation Loc,
228                                               llvm::StringRef Namespace) {
229   beginCallback("PragmaDiagnosticPush");
230   appendArgument("Loc", Loc);
231   appendArgument("Namespace", Namespace);
232 }
233
234 // Callback invoked when a #pragma gcc diagnostic pop directive
235 // is read.
236 void PPCallbacksTracker::PragmaDiagnosticPop(SourceLocation Loc,
237                                              llvm::StringRef Namespace) {
238   beginCallback("PragmaDiagnosticPop");
239   appendArgument("Loc", Loc);
240   appendArgument("Namespace", Namespace);
241 }
242
243 // Callback invoked when a #pragma gcc diagnostic directive is read.
244 void PPCallbacksTracker::PragmaDiagnostic(SourceLocation Loc,
245                                           llvm::StringRef Namespace,
246                                           diag::Severity Mapping,
247                                           llvm::StringRef Str) {
248   beginCallback("PragmaDiagnostic");
249   appendArgument("Loc", Loc);
250   appendArgument("Namespace", Namespace);
251   appendArgument("Mapping", (unsigned)Mapping, MappingStrings);
252   appendArgument("Str", Str);
253 }
254
255 // Called when an OpenCL extension is either disabled or
256 // enabled with a pragma.
257 void PPCallbacksTracker::PragmaOpenCLExtension(SourceLocation NameLoc,
258                                                const IdentifierInfo *Name,
259                                                SourceLocation StateLoc,
260                                                unsigned State) {
261   beginCallback("PragmaOpenCLExtension");
262   appendArgument("NameLoc", NameLoc);
263   appendArgument("Name", Name);
264   appendArgument("StateLoc", StateLoc);
265   appendArgument("State", (int)State);
266 }
267
268 // Callback invoked when a #pragma warning directive is read.
269 void PPCallbacksTracker::PragmaWarning(SourceLocation Loc,
270                                        llvm::StringRef WarningSpec,
271                                        llvm::ArrayRef<int> Ids) {
272   beginCallback("PragmaWarning");
273   appendArgument("Loc", Loc);
274   appendArgument("WarningSpec", WarningSpec);
275
276   std::string Str;
277   llvm::raw_string_ostream SS(Str);
278   SS << "[";
279   for (int i = 0, e = Ids.size(); i != e; ++i) {
280     if (i)
281       SS << ", ";
282     SS << Ids[i];
283   }
284   SS << "]";
285   appendArgument("Ids", SS.str());
286 }
287
288 // Callback invoked when a #pragma warning(push) directive is read.
289 void PPCallbacksTracker::PragmaWarningPush(SourceLocation Loc, int Level) {
290   beginCallback("PragmaWarningPush");
291   appendArgument("Loc", Loc);
292   appendArgument("Level", Level);
293 }
294
295 // Callback invoked when a #pragma warning(pop) directive is read.
296 void PPCallbacksTracker::PragmaWarningPop(SourceLocation Loc) {
297   beginCallback("PragmaWarningPop");
298   appendArgument("Loc", Loc);
299 }
300
301 // Callback invoked when a #pragma execution_character_set(push) directive
302 // is read.
303 void PPCallbacksTracker::PragmaExecCharsetPush(SourceLocation Loc,
304                                                StringRef Str) {
305   beginCallback("PragmaExecCharsetPush");
306   appendArgument("Loc", Loc);
307   appendArgument("Charset", Str);
308 }
309
310 // Callback invoked when a #pragma execution_character_set(pop) directive
311 // is read.
312 void PPCallbacksTracker::PragmaExecCharsetPop(SourceLocation Loc) {
313   beginCallback("PragmaExecCharsetPop");
314   appendArgument("Loc", Loc);
315 }
316
317 // Called by Preprocessor::HandleMacroExpandedIdentifier when a
318 // macro invocation is found.
319 void PPCallbacksTracker::MacroExpands(const Token &MacroNameTok,
320                                       const MacroDefinition &MacroDefinition,
321                                       SourceRange Range,
322                                       const MacroArgs *Args) {
323   beginCallback("MacroExpands");
324   appendArgument("MacroNameTok", MacroNameTok);
325   appendArgument("MacroDefinition", MacroDefinition);
326   appendArgument("Range", Range);
327   appendArgument("Args", Args);
328 }
329
330 // Hook called whenever a macro definition is seen.
331 void PPCallbacksTracker::MacroDefined(const Token &MacroNameTok,
332                                       const MacroDirective *MacroDirective) {
333   beginCallback("MacroDefined");
334   appendArgument("MacroNameTok", MacroNameTok);
335   appendArgument("MacroDirective", MacroDirective);
336 }
337
338 // Hook called whenever a macro #undef is seen.
339 void PPCallbacksTracker::MacroUndefined(const Token &MacroNameTok,
340                                         const MacroDefinition &MacroDefinition,
341                                         const MacroDirective *Undef) {
342   beginCallback("MacroUndefined");
343   appendArgument("MacroNameTok", MacroNameTok);
344   appendArgument("MacroDefinition", MacroDefinition);
345 }
346
347 // Hook called whenever the 'defined' operator is seen.
348 void PPCallbacksTracker::Defined(const Token &MacroNameTok,
349                                  const MacroDefinition &MacroDefinition,
350                                  SourceRange Range) {
351   beginCallback("Defined");
352   appendArgument("MacroNameTok", MacroNameTok);
353   appendArgument("MacroDefinition", MacroDefinition);
354   appendArgument("Range", Range);
355 }
356
357 // Hook called when a source range is skipped.
358 void PPCallbacksTracker::SourceRangeSkipped(SourceRange Range,
359                                             SourceLocation EndifLoc) {
360   beginCallback("SourceRangeSkipped");
361   appendArgument("Range", SourceRange(Range.getBegin(), EndifLoc));
362 }
363
364 // Hook called whenever an #if is seen.
365 void PPCallbacksTracker::If(SourceLocation Loc, SourceRange ConditionRange,
366                             ConditionValueKind ConditionValue) {
367   beginCallback("If");
368   appendArgument("Loc", Loc);
369   appendArgument("ConditionRange", ConditionRange);
370   appendArgument("ConditionValue", ConditionValue, ConditionValueKindStrings);
371 }
372
373 // Hook called whenever an #elif is seen.
374 void PPCallbacksTracker::Elif(SourceLocation Loc, SourceRange ConditionRange,
375                               ConditionValueKind ConditionValue,
376                               SourceLocation IfLoc) {
377   beginCallback("Elif");
378   appendArgument("Loc", Loc);
379   appendArgument("ConditionRange", ConditionRange);
380   appendArgument("ConditionValue", ConditionValue, ConditionValueKindStrings);
381   appendArgument("IfLoc", IfLoc);
382 }
383
384 // Hook called whenever an #ifdef is seen.
385 void PPCallbacksTracker::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
386                                const MacroDefinition &MacroDefinition) {
387   beginCallback("Ifdef");
388   appendArgument("Loc", Loc);
389   appendArgument("MacroNameTok", MacroNameTok);
390   appendArgument("MacroDefinition", MacroDefinition);
391 }
392
393 // Hook called whenever an #ifndef is seen.
394 void PPCallbacksTracker::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
395                                 const MacroDefinition &MacroDefinition) {
396   beginCallback("Ifndef");
397   appendArgument("Loc", Loc);
398   appendArgument("MacroNameTok", MacroNameTok);
399   appendArgument("MacroDefinition", MacroDefinition);
400 }
401
402 // Hook called whenever an #else is seen.
403 void PPCallbacksTracker::Else(SourceLocation Loc, SourceLocation IfLoc) {
404   beginCallback("Else");
405   appendArgument("Loc", Loc);
406   appendArgument("IfLoc", IfLoc);
407 }
408
409 // Hook called whenever an #endif is seen.
410 void PPCallbacksTracker::Endif(SourceLocation Loc, SourceLocation IfLoc) {
411   beginCallback("Endif");
412   appendArgument("Loc", Loc);
413   appendArgument("IfLoc", IfLoc);
414 }
415
416 // Helper functions.
417
418 // Start a new callback.
419 void PPCallbacksTracker::beginCallback(const char *Name) {
420   auto R = CallbackIsEnabled.try_emplace(Name, false);
421   if (R.second) {
422     llvm::StringRef N(Name);
423     for (const std::pair<llvm::GlobPattern, bool> &Filter : Filters)
424       if (Filter.first.match(N))
425         R.first->second = Filter.second;
426   }
427   DisableTrace = !R.first->second;
428   if (DisableTrace)
429     return;
430   CallbackCalls.push_back(CallbackCall(Name));
431 }
432
433 // Append a bool argument to the top trace item.
434 void PPCallbacksTracker::appendArgument(const char *Name, bool Value) {
435   appendArgument(Name, (Value ? "true" : "false"));
436 }
437
438 // Append an int argument to the top trace item.
439 void PPCallbacksTracker::appendArgument(const char *Name, int Value) {
440   std::string Str;
441   llvm::raw_string_ostream SS(Str);
442   SS << Value;
443   appendArgument(Name, SS.str());
444 }
445
446 // Append a string argument to the top trace item.
447 void PPCallbacksTracker::appendArgument(const char *Name, const char *Value) {
448   if (DisableTrace)
449     return;
450   CallbackCalls.back().Arguments.push_back(Argument{Name, Value});
451 }
452
453 // Append a string object argument to the top trace item.
454 void PPCallbacksTracker::appendArgument(const char *Name,
455                                         llvm::StringRef Value) {
456   appendArgument(Name, Value.str());
457 }
458
459 // Append a string object argument to the top trace item.
460 void PPCallbacksTracker::appendArgument(const char *Name,
461                                         const std::string &Value) {
462   appendArgument(Name, Value.c_str());
463 }
464
465 // Append a token argument to the top trace item.
466 void PPCallbacksTracker::appendArgument(const char *Name, const Token &Value) {
467   appendArgument(Name, PP.getSpelling(Value));
468 }
469
470 // Append an enum argument to the top trace item.
471 void PPCallbacksTracker::appendArgument(const char *Name, int Value,
472                                         const char *const Strings[]) {
473   appendArgument(Name, Strings[Value]);
474 }
475
476 // Append a FileID argument to the top trace item.
477 void PPCallbacksTracker::appendArgument(const char *Name, FileID Value) {
478   if (Value.isInvalid()) {
479     appendArgument(Name, "(invalid)");
480     return;
481   }
482   const FileEntry *FileEntry = PP.getSourceManager().getFileEntryForID(Value);
483   if (!FileEntry) {
484     appendArgument(Name, "(getFileEntryForID failed)");
485     return;
486   }
487   appendFilePathArgument(Name, FileEntry->getName());
488 }
489
490 // Append a FileEntry argument to the top trace item.
491 void PPCallbacksTracker::appendArgument(const char *Name,
492                                         const FileEntry *Value) {
493   if (!Value) {
494     appendArgument(Name, "(null)");
495     return;
496   }
497   appendFilePathArgument(Name, Value->getName());
498 }
499
500 // Append a SourceLocation argument to the top trace item.
501 void PPCallbacksTracker::appendArgument(const char *Name,
502                                         SourceLocation Value) {
503   if (Value.isInvalid()) {
504     appendArgument(Name, "(invalid)");
505     return;
506   }
507   appendArgument(Name, getSourceLocationString(PP, Value).c_str());
508 }
509
510 // Append a SourceRange argument to the top trace item.
511 void PPCallbacksTracker::appendArgument(const char *Name, SourceRange Value) {
512   if (DisableTrace)
513     return;
514   if (Value.isInvalid()) {
515     appendArgument(Name, "(invalid)");
516     return;
517   }
518   std::string Str;
519   llvm::raw_string_ostream SS(Str);
520   SS << "[" << getSourceLocationString(PP, Value.getBegin()) << ", "
521      << getSourceLocationString(PP, Value.getEnd()) << "]";
522   appendArgument(Name, SS.str());
523 }
524
525 // Append a CharSourceRange argument to the top trace item.
526 void PPCallbacksTracker::appendArgument(const char *Name,
527                                         CharSourceRange Value) {
528   if (Value.isInvalid()) {
529     appendArgument(Name, "(invalid)");
530     return;
531   }
532   appendArgument(Name, getSourceString(Value).str().c_str());
533 }
534
535 // Append a SourceLocation argument to the top trace item.
536 void PPCallbacksTracker::appendArgument(const char *Name, ModuleIdPath Value) {
537   if (DisableTrace)
538     return;
539   std::string Str;
540   llvm::raw_string_ostream SS(Str);
541   SS << "[";
542   for (int I = 0, E = Value.size(); I != E; ++I) {
543     if (I)
544       SS << ", ";
545     SS << "{"
546        << "Name: " << Value[I].first->getName() << ", "
547        << "Loc: " << getSourceLocationString(PP, Value[I].second) << "}";
548   }
549   SS << "]";
550   appendArgument(Name, SS.str());
551 }
552
553 // Append an IdentifierInfo argument to the top trace item.
554 void PPCallbacksTracker::appendArgument(const char *Name,
555                                         const IdentifierInfo *Value) {
556   if (!Value) {
557     appendArgument(Name, "(null)");
558     return;
559   }
560   appendArgument(Name, Value->getName().str().c_str());
561 }
562
563 // Append a MacroDirective argument to the top trace item.
564 void PPCallbacksTracker::appendArgument(const char *Name,
565                                         const MacroDirective *Value) {
566   if (!Value) {
567     appendArgument(Name, "(null)");
568     return;
569   }
570   appendArgument(Name, MacroDirectiveKindStrings[Value->getKind()]);
571 }
572
573 // Append a MacroDefinition argument to the top trace item.
574 void PPCallbacksTracker::appendArgument(const char *Name,
575                                         const MacroDefinition &Value) {
576   std::string Str;
577   llvm::raw_string_ostream SS(Str);
578   SS << "[";
579   bool Any = false;
580   if (Value.getLocalDirective()) {
581     SS << "(local)";
582     Any = true;
583   }
584   for (auto *MM : Value.getModuleMacros()) {
585     if (Any) SS << ", ";
586     SS << MM->getOwningModule()->getFullModuleName();
587   }
588   SS << "]";
589   appendArgument(Name, SS.str());
590 }
591
592 // Append a MacroArgs argument to the top trace item.
593 void PPCallbacksTracker::appendArgument(const char *Name,
594                                         const MacroArgs *Value) {
595   if (!Value) {
596     appendArgument(Name, "(null)");
597     return;
598   }
599   std::string Str;
600   llvm::raw_string_ostream SS(Str);
601   SS << "[";
602
603   // Each argument is is a series of contiguous Tokens, terminated by a eof.
604   // Go through each argument printing tokens until we reach eof.
605   for (unsigned I = 0; I < Value->getNumMacroArguments(); ++I) {
606     const Token *Current = Value->getUnexpArgument(I);
607     if (I)
608       SS << ", ";
609     bool First = true;
610     while (Current->isNot(tok::eof)) {
611       if (!First)
612         SS << " ";
613       // We need to be careful here because the arguments might not be legal in
614       // YAML, so we use the token name for anything but identifiers and
615       // numeric literals.
616       if (Current->isAnyIdentifier() || Current->is(tok::numeric_constant)) {
617         SS << PP.getSpelling(*Current);
618       } else {
619         SS << "<" << Current->getName() << ">";
620       }
621       ++Current;
622       First = false;
623     }
624   }
625   SS << "]";
626   appendArgument(Name, SS.str());
627 }
628
629 // Append a Module argument to the top trace item.
630 void PPCallbacksTracker::appendArgument(const char *Name, const Module *Value) {
631   if (!Value) {
632     appendArgument(Name, "(null)");
633     return;
634   }
635   appendArgument(Name, Value->Name.c_str());
636 }
637
638 // Append a double-quoted argument to the top trace item.
639 void PPCallbacksTracker::appendQuotedArgument(const char *Name,
640                                               const std::string &Value) {
641   std::string Str;
642   llvm::raw_string_ostream SS(Str);
643   SS << "\"" << Value << "\"";
644   appendArgument(Name, SS.str());
645 }
646
647 // Append a double-quoted file path argument to the top trace item.
648 void PPCallbacksTracker::appendFilePathArgument(const char *Name,
649                                                 llvm::StringRef Value) {
650   std::string Path(Value);
651   // YAML treats backslash as escape, so use forward slashes.
652   std::replace(Path.begin(), Path.end(), '\\', '/');
653   appendQuotedArgument(Name, Path);
654 }
655
656 // Get the raw source string of the range.
657 llvm::StringRef PPCallbacksTracker::getSourceString(CharSourceRange Range) {
658   const char *B = PP.getSourceManager().getCharacterData(Range.getBegin());
659   const char *E = PP.getSourceManager().getCharacterData(Range.getEnd());
660   return llvm::StringRef(B, E - B);
661 }
662
663 } // namespace pp_trace
664 } // namespace clang