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); 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, Optional<FileEntryRef> 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. 153 void 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. 164 void PPCallbacksTracker::EndOfMainFile() { beginCallback("EndOfMainFile"); } 165 166 // Callback invoked when a #ident or #sccs directive is read. 167 void 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. 174 void 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. 182 void 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. 193 void 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. 203 void 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. 211 void 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. 224 void 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. 233 void 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. 241 void 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. 254 void 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. 266 void 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. 286 void 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. 293 void 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. 300 void 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. 309 void 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. 316 void 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. 328 void 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. 336 void 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. 345 void 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. 355 void 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. 362 void 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. 371 void 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. 382 void 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. 391 void 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. 400 void 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. 407 void 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. 416 void 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. 431 void 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. 436 void 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. 444 void 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. 451 void 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. 457 void 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. 463 void 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. 468 void 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. 474 void 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. 488 void PPCallbacksTracker::appendArgument(const char *Name, 489 Optional<FileEntryRef> Value) { 490 if (!Value) { 491 appendArgument(Name, "(null)"); 492 return; 493 } 494 appendArgument(Name, *Value); 495 } 496 497 void PPCallbacksTracker::appendArgument(const char *Name, FileEntryRef Value) { 498 appendFilePathArgument(Name, Value.getName()); 499 } 500 501 // Append a SourceLocation argument to the top trace item. 502 void 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. 512 void 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. 527 void 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. 537 void 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. 555 void 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. 565 void 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. 575 void 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. 594 void 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. 631 void 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. 640 void 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. 649 void 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. 658 llvm::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