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