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