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