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