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 665