1 //===--- PlistDiagnostics.cpp - Plist Diagnostics for Paths -----*- C++ -*-===// 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 // This file defines the PlistDiagnostics object. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/Analysis/IssueHash.h" 14 #include "clang/Analysis/PathDiagnostic.h" 15 #include "clang/Basic/FileManager.h" 16 #include "clang/Basic/PlistSupport.h" 17 #include "clang/Basic/SourceManager.h" 18 #include "clang/Basic/Version.h" 19 #include "clang/CrossTU/CrossTranslationUnit.h" 20 #include "clang/Frontend/ASTUnit.h" 21 #include "clang/Lex/Preprocessor.h" 22 #include "clang/Lex/TokenConcatenation.h" 23 #include "clang/Rewrite/Core/HTMLRewrite.h" 24 #include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" 25 #include "llvm/ADT/SmallPtrSet.h" 26 #include "llvm/ADT/SmallVector.h" 27 #include "llvm/ADT/Statistic.h" 28 #include "llvm/Support/Casting.h" 29 #include <memory> 30 31 using namespace clang; 32 using namespace ento; 33 using namespace markup; 34 35 //===----------------------------------------------------------------------===// 36 // Declarations of helper classes and functions for emitting bug reports in 37 // plist format. 38 //===----------------------------------------------------------------------===// 39 40 namespace { 41 class PlistDiagnostics : public PathDiagnosticConsumer { 42 PathDiagnosticConsumerOptions DiagOpts; 43 const std::string OutputFile; 44 const Preprocessor &PP; 45 const cross_tu::CrossTranslationUnitContext &CTU; 46 const bool SupportsCrossFileDiagnostics; 47 48 void printBugPath(llvm::raw_ostream &o, const FIDMap &FM, 49 const PathPieces &Path); 50 51 public: 52 PlistDiagnostics(PathDiagnosticConsumerOptions DiagOpts, 53 const std::string &OutputFile, const Preprocessor &PP, 54 const cross_tu::CrossTranslationUnitContext &CTU, 55 bool supportsMultipleFiles); 56 57 ~PlistDiagnostics() override {} 58 59 void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags, 60 FilesMade *filesMade) override; 61 62 StringRef getName() const override { 63 return "PlistDiagnostics"; 64 } 65 66 PathGenerationScheme getGenerationScheme() const override { 67 return Extensive; 68 } 69 bool supportsLogicalOpControlFlow() const override { return true; } 70 bool supportsCrossFileDiagnostics() const override { 71 return SupportsCrossFileDiagnostics; 72 } 73 }; 74 } // end anonymous namespace 75 76 namespace { 77 78 /// A helper class for emitting a single report. 79 class PlistPrinter { 80 const FIDMap& FM; 81 const Preprocessor &PP; 82 const cross_tu::CrossTranslationUnitContext &CTU; 83 llvm::SmallVector<const PathDiagnosticMacroPiece *, 0> MacroPieces; 84 85 public: 86 PlistPrinter(const FIDMap& FM, 87 const Preprocessor &PP, 88 const cross_tu::CrossTranslationUnitContext &CTU) 89 : FM(FM), PP(PP), CTU(CTU) { 90 } 91 92 void ReportDiag(raw_ostream &o, const PathDiagnosticPiece& P) { 93 ReportPiece(o, P, /*indent*/ 4, /*depth*/ 0, /*includeControlFlow*/ true); 94 } 95 96 /// Print the expansions of the collected macro pieces. 97 /// 98 /// Each time ReportDiag is called on a PathDiagnosticMacroPiece (or, if one 99 /// is found through a call piece, etc), it's subpieces are reported, and the 100 /// piece itself is collected. Call this function after the entire bugpath 101 /// was reported. 102 void ReportMacroExpansions(raw_ostream &o, unsigned indent); 103 104 private: 105 void ReportPiece(raw_ostream &o, const PathDiagnosticPiece &P, 106 unsigned indent, unsigned depth, bool includeControlFlow, 107 bool isKeyEvent = false) { 108 switch (P.getKind()) { 109 case PathDiagnosticPiece::ControlFlow: 110 if (includeControlFlow) 111 ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), indent); 112 break; 113 case PathDiagnosticPiece::Call: 114 ReportCall(o, cast<PathDiagnosticCallPiece>(P), indent, 115 depth); 116 break; 117 case PathDiagnosticPiece::Event: 118 ReportEvent(o, cast<PathDiagnosticEventPiece>(P), indent, depth, 119 isKeyEvent); 120 break; 121 case PathDiagnosticPiece::Macro: 122 ReportMacroSubPieces(o, cast<PathDiagnosticMacroPiece>(P), indent, 123 depth); 124 break; 125 case PathDiagnosticPiece::Note: 126 ReportNote(o, cast<PathDiagnosticNotePiece>(P), indent); 127 break; 128 case PathDiagnosticPiece::PopUp: 129 ReportPopUp(o, cast<PathDiagnosticPopUpPiece>(P), indent); 130 break; 131 } 132 } 133 134 void EmitRanges(raw_ostream &o, const ArrayRef<SourceRange> Ranges, 135 unsigned indent); 136 void EmitMessage(raw_ostream &o, StringRef Message, unsigned indent); 137 void EmitFixits(raw_ostream &o, ArrayRef<FixItHint> fixits, unsigned indent); 138 139 void ReportControlFlow(raw_ostream &o, 140 const PathDiagnosticControlFlowPiece& P, 141 unsigned indent); 142 void ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P, 143 unsigned indent, unsigned depth, bool isKeyEvent = false); 144 void ReportCall(raw_ostream &o, const PathDiagnosticCallPiece &P, 145 unsigned indent, unsigned depth); 146 void ReportMacroSubPieces(raw_ostream &o, const PathDiagnosticMacroPiece& P, 147 unsigned indent, unsigned depth); 148 void ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P, 149 unsigned indent); 150 151 void ReportPopUp(raw_ostream &o, const PathDiagnosticPopUpPiece &P, 152 unsigned indent); 153 }; 154 155 } // end of anonymous namespace 156 157 namespace { 158 159 struct ExpansionInfo { 160 std::string MacroName; 161 std::string Expansion; 162 ExpansionInfo(std::string N, std::string E) 163 : MacroName(std::move(N)), Expansion(std::move(E)) {} 164 }; 165 166 } // end of anonymous namespace 167 168 /// Print coverage information to output stream {@code o}. 169 /// May modify the used list of files {@code Fids} by inserting new ones. 170 static void printCoverage(const PathDiagnostic *D, 171 unsigned InputIndentLevel, 172 SmallVectorImpl<FileID> &Fids, 173 FIDMap &FM, 174 llvm::raw_fd_ostream &o); 175 176 static ExpansionInfo 177 getExpandedMacro(SourceLocation MacroLoc, const Preprocessor &PP, 178 const cross_tu::CrossTranslationUnitContext &CTU); 179 180 //===----------------------------------------------------------------------===// 181 // Methods of PlistPrinter. 182 //===----------------------------------------------------------------------===// 183 184 void PlistPrinter::EmitRanges(raw_ostream &o, 185 const ArrayRef<SourceRange> Ranges, 186 unsigned indent) { 187 188 if (Ranges.empty()) 189 return; 190 191 Indent(o, indent) << "<key>ranges</key>\n"; 192 Indent(o, indent) << "<array>\n"; 193 ++indent; 194 195 const SourceManager &SM = PP.getSourceManager(); 196 const LangOptions &LangOpts = PP.getLangOpts(); 197 198 for (auto &R : Ranges) 199 EmitRange(o, SM, 200 Lexer::getAsCharRange(SM.getExpansionRange(R), SM, LangOpts), 201 FM, indent + 1); 202 --indent; 203 Indent(o, indent) << "</array>\n"; 204 } 205 206 void PlistPrinter::EmitMessage(raw_ostream &o, StringRef Message, 207 unsigned indent) { 208 // Output the text. 209 assert(!Message.empty()); 210 Indent(o, indent) << "<key>extended_message</key>\n"; 211 Indent(o, indent); 212 EmitString(o, Message) << '\n'; 213 214 // Output the short text. 215 // FIXME: Really use a short string. 216 Indent(o, indent) << "<key>message</key>\n"; 217 Indent(o, indent); 218 EmitString(o, Message) << '\n'; 219 } 220 221 void PlistPrinter::EmitFixits(raw_ostream &o, ArrayRef<FixItHint> fixits, 222 unsigned indent) { 223 if (fixits.size() == 0) 224 return; 225 226 const SourceManager &SM = PP.getSourceManager(); 227 const LangOptions &LangOpts = PP.getLangOpts(); 228 229 Indent(o, indent) << "<key>fixits</key>\n"; 230 Indent(o, indent) << "<array>\n"; 231 for (const auto &fixit : fixits) { 232 assert(!fixit.isNull()); 233 // FIXME: Add support for InsertFromRange and BeforePreviousInsertion. 234 assert(!fixit.InsertFromRange.isValid() && "Not implemented yet!"); 235 assert(!fixit.BeforePreviousInsertions && "Not implemented yet!"); 236 Indent(o, indent) << " <dict>\n"; 237 Indent(o, indent) << " <key>remove_range</key>\n"; 238 EmitRange(o, SM, Lexer::getAsCharRange(fixit.RemoveRange, SM, LangOpts), 239 FM, indent + 2); 240 Indent(o, indent) << " <key>insert_string</key>"; 241 EmitString(o, fixit.CodeToInsert); 242 o << "\n"; 243 Indent(o, indent) << " </dict>\n"; 244 } 245 Indent(o, indent) << "</array>\n"; 246 } 247 248 void PlistPrinter::ReportControlFlow(raw_ostream &o, 249 const PathDiagnosticControlFlowPiece& P, 250 unsigned indent) { 251 252 const SourceManager &SM = PP.getSourceManager(); 253 const LangOptions &LangOpts = PP.getLangOpts(); 254 255 Indent(o, indent) << "<dict>\n"; 256 ++indent; 257 258 Indent(o, indent) << "<key>kind</key><string>control</string>\n"; 259 260 // Emit edges. 261 Indent(o, indent) << "<key>edges</key>\n"; 262 ++indent; 263 Indent(o, indent) << "<array>\n"; 264 ++indent; 265 for (PathDiagnosticControlFlowPiece::const_iterator I=P.begin(), E=P.end(); 266 I!=E; ++I) { 267 Indent(o, indent) << "<dict>\n"; 268 ++indent; 269 270 // Make the ranges of the start and end point self-consistent with adjacent edges 271 // by forcing to use only the beginning of the range. This simplifies the layout 272 // logic for clients. 273 Indent(o, indent) << "<key>start</key>\n"; 274 SourceRange StartEdge( 275 SM.getExpansionLoc(I->getStart().asRange().getBegin())); 276 EmitRange(o, SM, Lexer::getAsCharRange(StartEdge, SM, LangOpts), FM, 277 indent + 1); 278 279 Indent(o, indent) << "<key>end</key>\n"; 280 SourceRange EndEdge(SM.getExpansionLoc(I->getEnd().asRange().getBegin())); 281 EmitRange(o, SM, Lexer::getAsCharRange(EndEdge, SM, LangOpts), FM, 282 indent + 1); 283 284 --indent; 285 Indent(o, indent) << "</dict>\n"; 286 } 287 --indent; 288 Indent(o, indent) << "</array>\n"; 289 --indent; 290 291 // Output any helper text. 292 const auto &s = P.getString(); 293 if (!s.empty()) { 294 Indent(o, indent) << "<key>alternate</key>"; 295 EmitString(o, s) << '\n'; 296 } 297 298 assert(P.getFixits().size() == 0 && 299 "Fixits on constrol flow pieces are not implemented yet!"); 300 301 --indent; 302 Indent(o, indent) << "</dict>\n"; 303 } 304 305 void PlistPrinter::ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P, 306 unsigned indent, unsigned depth, 307 bool isKeyEvent) { 308 309 const SourceManager &SM = PP.getSourceManager(); 310 311 Indent(o, indent) << "<dict>\n"; 312 ++indent; 313 314 Indent(o, indent) << "<key>kind</key><string>event</string>\n"; 315 316 if (isKeyEvent) { 317 Indent(o, indent) << "<key>key_event</key><true/>\n"; 318 } 319 320 // Output the location. 321 FullSourceLoc L = P.getLocation().asLocation(); 322 323 Indent(o, indent) << "<key>location</key>\n"; 324 EmitLocation(o, SM, L, FM, indent); 325 326 // Output the ranges (if any). 327 ArrayRef<SourceRange> Ranges = P.getRanges(); 328 EmitRanges(o, Ranges, indent); 329 330 // Output the call depth. 331 Indent(o, indent) << "<key>depth</key>"; 332 EmitInteger(o, depth) << '\n'; 333 334 // Output the text. 335 EmitMessage(o, P.getString(), indent); 336 337 // Output the fixits. 338 EmitFixits(o, P.getFixits(), indent); 339 340 // Finish up. 341 --indent; 342 Indent(o, indent); o << "</dict>\n"; 343 } 344 345 void PlistPrinter::ReportCall(raw_ostream &o, const PathDiagnosticCallPiece &P, 346 unsigned indent, 347 unsigned depth) { 348 349 if (auto callEnter = P.getCallEnterEvent()) 350 ReportPiece(o, *callEnter, indent, depth, /*includeControlFlow*/ true, 351 P.isLastInMainSourceFile()); 352 353 354 ++depth; 355 356 if (auto callEnterWithinCaller = P.getCallEnterWithinCallerEvent()) 357 ReportPiece(o, *callEnterWithinCaller, indent, depth, 358 /*includeControlFlow*/ true); 359 360 for (PathPieces::const_iterator I = P.path.begin(), E = P.path.end();I!=E;++I) 361 ReportPiece(o, **I, indent, depth, /*includeControlFlow*/ true); 362 363 --depth; 364 365 if (auto callExit = P.getCallExitEvent()) 366 ReportPiece(o, *callExit, indent, depth, /*includeControlFlow*/ true); 367 368 assert(P.getFixits().size() == 0 && 369 "Fixits on call pieces are not implemented yet!"); 370 } 371 372 void PlistPrinter::ReportMacroSubPieces(raw_ostream &o, 373 const PathDiagnosticMacroPiece& P, 374 unsigned indent, unsigned depth) { 375 MacroPieces.push_back(&P); 376 377 for (PathPieces::const_iterator I = P.subPieces.begin(), 378 E = P.subPieces.end(); 379 I != E; ++I) { 380 ReportPiece(o, **I, indent, depth, /*includeControlFlow*/ false); 381 } 382 383 assert(P.getFixits().size() == 0 && 384 "Fixits on constrol flow pieces are not implemented yet!"); 385 } 386 387 void PlistPrinter::ReportMacroExpansions(raw_ostream &o, unsigned indent) { 388 389 for (const PathDiagnosticMacroPiece *P : MacroPieces) { 390 const SourceManager &SM = PP.getSourceManager(); 391 ExpansionInfo EI = getExpandedMacro(P->getLocation().asLocation(), PP, CTU); 392 393 Indent(o, indent) << "<dict>\n"; 394 ++indent; 395 396 // Output the location. 397 FullSourceLoc L = P->getLocation().asLocation(); 398 399 Indent(o, indent) << "<key>location</key>\n"; 400 EmitLocation(o, SM, L, FM, indent); 401 402 // Output the ranges (if any). 403 ArrayRef<SourceRange> Ranges = P->getRanges(); 404 EmitRanges(o, Ranges, indent); 405 406 // Output the macro name. 407 Indent(o, indent) << "<key>name</key>"; 408 EmitString(o, EI.MacroName) << '\n'; 409 410 // Output what it expands into. 411 Indent(o, indent) << "<key>expansion</key>"; 412 EmitString(o, EI.Expansion) << '\n'; 413 414 // Finish up. 415 --indent; 416 Indent(o, indent); 417 o << "</dict>\n"; 418 } 419 } 420 421 void PlistPrinter::ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P, 422 unsigned indent) { 423 424 const SourceManager &SM = PP.getSourceManager(); 425 426 Indent(o, indent) << "<dict>\n"; 427 ++indent; 428 429 // Output the location. 430 FullSourceLoc L = P.getLocation().asLocation(); 431 432 Indent(o, indent) << "<key>location</key>\n"; 433 EmitLocation(o, SM, L, FM, indent); 434 435 // Output the ranges (if any). 436 ArrayRef<SourceRange> Ranges = P.getRanges(); 437 EmitRanges(o, Ranges, indent); 438 439 // Output the text. 440 EmitMessage(o, P.getString(), indent); 441 442 // Output the fixits. 443 EmitFixits(o, P.getFixits(), indent); 444 445 // Finish up. 446 --indent; 447 Indent(o, indent); o << "</dict>\n"; 448 } 449 450 void PlistPrinter::ReportPopUp(raw_ostream &o, 451 const PathDiagnosticPopUpPiece &P, 452 unsigned indent) { 453 const SourceManager &SM = PP.getSourceManager(); 454 455 Indent(o, indent) << "<dict>\n"; 456 ++indent; 457 458 Indent(o, indent) << "<key>kind</key><string>pop-up</string>\n"; 459 460 // Output the location. 461 FullSourceLoc L = P.getLocation().asLocation(); 462 463 Indent(o, indent) << "<key>location</key>\n"; 464 EmitLocation(o, SM, L, FM, indent); 465 466 // Output the ranges (if any). 467 ArrayRef<SourceRange> Ranges = P.getRanges(); 468 EmitRanges(o, Ranges, indent); 469 470 // Output the text. 471 EmitMessage(o, P.getString(), indent); 472 473 assert(P.getFixits().size() == 0 && 474 "Fixits on pop-up pieces are not implemented yet!"); 475 476 // Finish up. 477 --indent; 478 Indent(o, indent) << "</dict>\n"; 479 } 480 481 //===----------------------------------------------------------------------===// 482 // Static function definitions. 483 //===----------------------------------------------------------------------===// 484 485 /// Print coverage information to output stream {@code o}. 486 /// May modify the used list of files {@code Fids} by inserting new ones. 487 static void printCoverage(const PathDiagnostic *D, 488 unsigned InputIndentLevel, 489 SmallVectorImpl<FileID> &Fids, 490 FIDMap &FM, 491 llvm::raw_fd_ostream &o) { 492 unsigned IndentLevel = InputIndentLevel; 493 494 Indent(o, IndentLevel) << "<key>ExecutedLines</key>\n"; 495 Indent(o, IndentLevel) << "<dict>\n"; 496 IndentLevel++; 497 498 // Mapping from file IDs to executed lines. 499 const FilesToLineNumsMap &ExecutedLines = D->getExecutedLines(); 500 for (auto I = ExecutedLines.begin(), E = ExecutedLines.end(); I != E; ++I) { 501 unsigned FileKey = AddFID(FM, Fids, I->first); 502 Indent(o, IndentLevel) << "<key>" << FileKey << "</key>\n"; 503 Indent(o, IndentLevel) << "<array>\n"; 504 IndentLevel++; 505 for (unsigned LineNo : I->second) { 506 Indent(o, IndentLevel); 507 EmitInteger(o, LineNo) << "\n"; 508 } 509 IndentLevel--; 510 Indent(o, IndentLevel) << "</array>\n"; 511 } 512 IndentLevel--; 513 Indent(o, IndentLevel) << "</dict>\n"; 514 515 assert(IndentLevel == InputIndentLevel); 516 } 517 518 //===----------------------------------------------------------------------===// 519 // Methods of PlistDiagnostics. 520 //===----------------------------------------------------------------------===// 521 522 PlistDiagnostics::PlistDiagnostics( 523 PathDiagnosticConsumerOptions DiagOpts, const std::string &output, 524 const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU, 525 bool supportsMultipleFiles) 526 : DiagOpts(std::move(DiagOpts)), OutputFile(output), PP(PP), CTU(CTU), 527 SupportsCrossFileDiagnostics(supportsMultipleFiles) { 528 // FIXME: Will be used by a later planned change. 529 (void)this->CTU; 530 } 531 532 void ento::createPlistDiagnosticConsumer( 533 PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, 534 const std::string &OutputFile, const Preprocessor &PP, 535 const cross_tu::CrossTranslationUnitContext &CTU) { 536 537 // TODO: Emit an error here. 538 if (OutputFile.empty()) 539 return; 540 541 C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU, 542 /*supportsMultipleFiles=*/false)); 543 createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile, 544 PP, CTU); 545 } 546 547 void ento::createPlistMultiFileDiagnosticConsumer( 548 PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, 549 const std::string &OutputFile, const Preprocessor &PP, 550 const cross_tu::CrossTranslationUnitContext &CTU) { 551 552 // TODO: Emit an error here. 553 if (OutputFile.empty()) 554 return; 555 556 C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU, 557 /*supportsMultipleFiles=*/true)); 558 createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile, 559 PP, CTU); 560 } 561 562 void PlistDiagnostics::printBugPath(llvm::raw_ostream &o, const FIDMap &FM, 563 const PathPieces &Path) { 564 PlistPrinter Printer(FM, PP, CTU); 565 assert(std::is_partitioned(Path.begin(), Path.end(), 566 [](const PathDiagnosticPieceRef &E) { 567 return E->getKind() == PathDiagnosticPiece::Note; 568 }) && 569 "PathDiagnostic is not partitioned so that notes precede the rest"); 570 571 PathPieces::const_iterator FirstNonNote = std::partition_point( 572 Path.begin(), Path.end(), [](const PathDiagnosticPieceRef &E) { 573 return E->getKind() == PathDiagnosticPiece::Note; 574 }); 575 576 PathPieces::const_iterator I = Path.begin(); 577 578 if (FirstNonNote != Path.begin()) { 579 o << " <key>notes</key>\n" 580 " <array>\n"; 581 582 for (; I != FirstNonNote; ++I) 583 Printer.ReportDiag(o, **I); 584 585 o << " </array>\n"; 586 } 587 588 o << " <key>path</key>\n"; 589 590 o << " <array>\n"; 591 592 for (PathPieces::const_iterator E = Path.end(); I != E; ++I) 593 Printer.ReportDiag(o, **I); 594 595 o << " </array>\n"; 596 597 if (!DiagOpts.ShouldDisplayMacroExpansions) 598 return; 599 600 o << " <key>macro_expansions</key>\n" 601 " <array>\n"; 602 Printer.ReportMacroExpansions(o, /* indent */ 4); 603 o << " </array>\n"; 604 } 605 606 void PlistDiagnostics::FlushDiagnosticsImpl( 607 std::vector<const PathDiagnostic *> &Diags, 608 FilesMade *filesMade) { 609 // Build up a set of FIDs that we use by scanning the locations and 610 // ranges of the diagnostics. 611 FIDMap FM; 612 SmallVector<FileID, 10> Fids; 613 const SourceManager& SM = PP.getSourceManager(); 614 const LangOptions &LangOpts = PP.getLangOpts(); 615 616 auto AddPieceFID = [&FM, &Fids, &SM](const PathDiagnosticPiece &Piece) { 617 AddFID(FM, Fids, SM, Piece.getLocation().asLocation()); 618 ArrayRef<SourceRange> Ranges = Piece.getRanges(); 619 for (const SourceRange &Range : Ranges) { 620 AddFID(FM, Fids, SM, Range.getBegin()); 621 AddFID(FM, Fids, SM, Range.getEnd()); 622 } 623 }; 624 625 for (const PathDiagnostic *D : Diags) { 626 627 SmallVector<const PathPieces *, 5> WorkList; 628 WorkList.push_back(&D->path); 629 630 while (!WorkList.empty()) { 631 const PathPieces &Path = *WorkList.pop_back_val(); 632 633 for (const auto &Iter : Path) { 634 const PathDiagnosticPiece &Piece = *Iter; 635 AddPieceFID(Piece); 636 637 if (const PathDiagnosticCallPiece *Call = 638 dyn_cast<PathDiagnosticCallPiece>(&Piece)) { 639 if (auto CallEnterWithin = Call->getCallEnterWithinCallerEvent()) 640 AddPieceFID(*CallEnterWithin); 641 642 if (auto CallEnterEvent = Call->getCallEnterEvent()) 643 AddPieceFID(*CallEnterEvent); 644 645 WorkList.push_back(&Call->path); 646 } else if (const PathDiagnosticMacroPiece *Macro = 647 dyn_cast<PathDiagnosticMacroPiece>(&Piece)) { 648 WorkList.push_back(&Macro->subPieces); 649 } 650 } 651 } 652 } 653 654 // Open the file. 655 std::error_code EC; 656 llvm::raw_fd_ostream o(OutputFile, EC, llvm::sys::fs::OF_Text); 657 if (EC) { 658 llvm::errs() << "warning: could not create file: " << EC.message() << '\n'; 659 return; 660 } 661 662 EmitPlistHeader(o); 663 664 // Write the root object: a <dict> containing... 665 // - "clang_version", the string representation of clang version 666 // - "files", an <array> mapping from FIDs to file names 667 // - "diagnostics", an <array> containing the path diagnostics 668 o << "<dict>\n" << 669 " <key>clang_version</key>\n"; 670 EmitString(o, getClangFullVersion()) << '\n'; 671 o << " <key>diagnostics</key>\n" 672 " <array>\n"; 673 674 for (std::vector<const PathDiagnostic*>::iterator DI=Diags.begin(), 675 DE = Diags.end(); DI!=DE; ++DI) { 676 677 o << " <dict>\n"; 678 679 const PathDiagnostic *D = *DI; 680 printBugPath(o, FM, D->path); 681 682 // Output the bug type and bug category. 683 o << " <key>description</key>"; 684 EmitString(o, D->getShortDescription()) << '\n'; 685 o << " <key>category</key>"; 686 EmitString(o, D->getCategory()) << '\n'; 687 o << " <key>type</key>"; 688 EmitString(o, D->getBugType()) << '\n'; 689 o << " <key>check_name</key>"; 690 EmitString(o, D->getCheckerName()) << '\n'; 691 692 o << " <!-- This hash is experimental and going to change! -->\n"; 693 o << " <key>issue_hash_content_of_line_in_context</key>"; 694 PathDiagnosticLocation UPDLoc = D->getUniqueingLoc(); 695 FullSourceLoc L(SM.getExpansionLoc(UPDLoc.isValid() 696 ? UPDLoc.asLocation() 697 : D->getLocation().asLocation()), 698 SM); 699 const Decl *DeclWithIssue = D->getDeclWithIssue(); 700 EmitString(o, getIssueHash(L, D->getCheckerName(), D->getBugType(), 701 DeclWithIssue, LangOpts)) 702 << '\n'; 703 704 // Output information about the semantic context where 705 // the issue occurred. 706 if (const Decl *DeclWithIssue = D->getDeclWithIssue()) { 707 // FIXME: handle blocks, which have no name. 708 if (const NamedDecl *ND = dyn_cast<NamedDecl>(DeclWithIssue)) { 709 StringRef declKind; 710 switch (ND->getKind()) { 711 case Decl::CXXRecord: 712 declKind = "C++ class"; 713 break; 714 case Decl::CXXMethod: 715 declKind = "C++ method"; 716 break; 717 case Decl::ObjCMethod: 718 declKind = "Objective-C method"; 719 break; 720 case Decl::Function: 721 declKind = "function"; 722 break; 723 default: 724 break; 725 } 726 if (!declKind.empty()) { 727 const std::string &declName = ND->getDeclName().getAsString(); 728 o << " <key>issue_context_kind</key>"; 729 EmitString(o, declKind) << '\n'; 730 o << " <key>issue_context</key>"; 731 EmitString(o, declName) << '\n'; 732 } 733 734 // Output the bug hash for issue unique-ing. Currently, it's just an 735 // offset from the beginning of the function. 736 if (const Stmt *Body = DeclWithIssue->getBody()) { 737 738 // If the bug uniqueing location exists, use it for the hash. 739 // For example, this ensures that two leaks reported on the same line 740 // will have different issue_hashes and that the hash will identify 741 // the leak location even after code is added between the allocation 742 // site and the end of scope (leak report location). 743 if (UPDLoc.isValid()) { 744 FullSourceLoc UFunL( 745 SM.getExpansionLoc( 746 D->getUniqueingDecl()->getBody()->getBeginLoc()), 747 SM); 748 o << " <key>issue_hash_function_offset</key><string>" 749 << L.getExpansionLineNumber() - UFunL.getExpansionLineNumber() 750 << "</string>\n"; 751 752 // Otherwise, use the location on which the bug is reported. 753 } else { 754 FullSourceLoc FunL(SM.getExpansionLoc(Body->getBeginLoc()), SM); 755 o << " <key>issue_hash_function_offset</key><string>" 756 << L.getExpansionLineNumber() - FunL.getExpansionLineNumber() 757 << "</string>\n"; 758 } 759 760 } 761 } 762 } 763 764 // Output the location of the bug. 765 o << " <key>location</key>\n"; 766 EmitLocation(o, SM, D->getLocation().asLocation(), FM, 2); 767 768 // Output the diagnostic to the sub-diagnostic client, if any. 769 if (!filesMade->empty()) { 770 StringRef lastName; 771 PDFileEntry::ConsumerFiles *files = filesMade->getFiles(*D); 772 if (files) { 773 for (PDFileEntry::ConsumerFiles::const_iterator CI = files->begin(), 774 CE = files->end(); CI != CE; ++CI) { 775 StringRef newName = CI->first; 776 if (newName != lastName) { 777 if (!lastName.empty()) { 778 o << " </array>\n"; 779 } 780 lastName = newName; 781 o << " <key>" << lastName << "_files</key>\n"; 782 o << " <array>\n"; 783 } 784 o << " <string>" << CI->second << "</string>\n"; 785 } 786 o << " </array>\n"; 787 } 788 } 789 790 printCoverage(D, /*IndentLevel=*/2, Fids, FM, o); 791 792 // Close up the entry. 793 o << " </dict>\n"; 794 } 795 796 o << " </array>\n"; 797 798 o << " <key>files</key>\n" 799 " <array>\n"; 800 for (FileID FID : Fids) 801 EmitString(o << " ", SM.getFileEntryForID(FID)->getName()) << '\n'; 802 o << " </array>\n"; 803 804 if (llvm::AreStatisticsEnabled() && DiagOpts.ShouldSerializeStats) { 805 o << " <key>statistics</key>\n"; 806 std::string stats; 807 llvm::raw_string_ostream os(stats); 808 llvm::PrintStatisticsJSON(os); 809 os.flush(); 810 EmitString(o, html::EscapeText(stats)) << '\n'; 811 } 812 813 // Finish. 814 o << "</dict>\n</plist>\n"; 815 } 816 817 //===----------------------------------------------------------------------===// 818 // Declarations of helper functions and data structures for expanding macros. 819 //===----------------------------------------------------------------------===// 820 821 namespace { 822 823 using ArgTokensTy = llvm::SmallVector<Token, 2>; 824 825 } // end of anonymous namespace 826 827 LLVM_DUMP_METHOD static void dumpArgTokensToStream(llvm::raw_ostream &Out, 828 const Preprocessor &PP, 829 const ArgTokensTy &Toks); 830 831 namespace { 832 /// Maps unexpanded macro parameters to expanded arguments. A macro argument may 833 /// need to expanded further when it is nested inside another macro. 834 class MacroParamMap : public std::map<const IdentifierInfo *, ArgTokensTy> { 835 public: 836 void expandFromPrevMacro(const MacroParamMap &Super); 837 838 LLVM_DUMP_METHOD void dump(const Preprocessor &PP) const { 839 dumpToStream(llvm::errs(), PP); 840 } 841 842 LLVM_DUMP_METHOD void dumpToStream(llvm::raw_ostream &Out, 843 const Preprocessor &PP) const; 844 }; 845 846 struct MacroExpansionInfo { 847 std::string Name; 848 const MacroInfo *MI = nullptr; 849 MacroParamMap ParamMap; 850 851 MacroExpansionInfo(std::string N, const MacroInfo *MI, MacroParamMap M) 852 : Name(std::move(N)), MI(MI), ParamMap(std::move(M)) {} 853 }; 854 855 class TokenPrinter { 856 llvm::raw_ostream &OS; 857 const Preprocessor &PP; 858 859 Token PrevTok, PrevPrevTok; 860 TokenConcatenation ConcatInfo; 861 862 public: 863 TokenPrinter(llvm::raw_ostream &OS, const Preprocessor &PP) 864 : OS(OS), PP(PP), ConcatInfo(PP) { 865 PrevTok.setKind(tok::unknown); 866 PrevPrevTok.setKind(tok::unknown); 867 } 868 869 void printToken(const Token &Tok); 870 }; 871 872 /// Wrapper around a Lexer object that can lex tokens one-by-one. Its possible 873 /// to "inject" a range of tokens into the stream, in which case the next token 874 /// is retrieved from the next element of the range, until the end of the range 875 /// is reached. 876 class TokenStream { 877 public: 878 TokenStream(SourceLocation ExpanLoc, const SourceManager &SM, 879 const LangOptions &LangOpts) 880 : ExpanLoc(ExpanLoc) { 881 FileID File; 882 unsigned Offset; 883 std::tie(File, Offset) = SM.getDecomposedLoc(ExpanLoc); 884 llvm::MemoryBufferRef MB = SM.getBufferOrFake(File); 885 const char *MacroNameTokenPos = MB.getBufferStart() + Offset; 886 887 RawLexer = std::make_unique<Lexer>(SM.getLocForStartOfFile(File), LangOpts, 888 MB.getBufferStart(), MacroNameTokenPos, 889 MB.getBufferEnd()); 890 } 891 892 void next(Token &Result) { 893 if (CurrTokenIt == TokenRange.end()) { 894 RawLexer->LexFromRawLexer(Result); 895 return; 896 } 897 Result = *CurrTokenIt; 898 CurrTokenIt++; 899 } 900 901 void injectRange(const ArgTokensTy &Range) { 902 TokenRange = Range; 903 CurrTokenIt = TokenRange.begin(); 904 } 905 906 std::unique_ptr<Lexer> RawLexer; 907 ArgTokensTy TokenRange; 908 ArgTokensTy::iterator CurrTokenIt = TokenRange.begin(); 909 SourceLocation ExpanLoc; 910 }; 911 912 } // end of anonymous namespace 913 914 /// The implementation method of getMacroExpansion: It prints the expansion of 915 /// a macro to \p Printer, and returns with the name of the macro. 916 /// 917 /// Since macros can be nested in one another, this function may call itself 918 /// recursively. 919 /// 920 /// Unfortunately, macro arguments have to expanded manually. To understand why, 921 /// observe the following example: 922 /// 923 /// #define PRINT(x) print(x) 924 /// #define DO_SOMETHING(str) PRINT(str) 925 /// 926 /// DO_SOMETHING("Cute panda cubs."); 927 /// 928 /// As we expand the last line, we'll immediately replace PRINT(str) with 929 /// print(x). The information that both 'str' and 'x' refers to the same string 930 /// is an information we have to forward, hence the argument \p PrevParamMap. 931 /// 932 /// To avoid infinite recursion we maintain the already processed tokens in 933 /// a set. This is carried as a parameter through the recursive calls. The set 934 /// is extended with the currently processed token and after processing it, the 935 /// token is removed. If the token is already in the set, then recursion stops: 936 /// 937 /// #define f(y) x 938 /// #define x f(x) 939 static std::string getMacroNameAndPrintExpansion( 940 TokenPrinter &Printer, SourceLocation MacroLoc, const Preprocessor &PP, 941 const MacroParamMap &PrevParamMap, 942 llvm::SmallPtrSet<IdentifierInfo *, 8> &AlreadyProcessedTokens); 943 944 /// Retrieves the name of the macro and what it's parameters expand into 945 /// at \p ExpanLoc. 946 /// 947 /// For example, for the following macro expansion: 948 /// 949 /// #define SET_TO_NULL(x) x = 0 950 /// #define NOT_SUSPICIOUS(a) \ 951 /// { \ 952 /// int b = 0; \ 953 /// } \ 954 /// SET_TO_NULL(a) 955 /// 956 /// int *ptr = new int(4); 957 /// NOT_SUSPICIOUS(&ptr); 958 /// *ptr = 5; 959 /// 960 /// When \p ExpanLoc references the last line, the macro name "NOT_SUSPICIOUS" 961 /// and the MacroArgMap map { (a, &ptr) } will be returned. 962 /// 963 /// When \p ExpanLoc references "SET_TO_NULL(a)" within the definition of 964 /// "NOT_SUSPICOUS", the macro name "SET_TO_NULL" and the MacroArgMap map 965 /// { (x, a) } will be returned. 966 static MacroExpansionInfo 967 getMacroExpansionInfo(const MacroParamMap &PrevParamMap, 968 SourceLocation ExpanLoc, const Preprocessor &PP); 969 970 /// Retrieves the ')' token that matches '(' \p It points to. 971 static MacroInfo::tokens_iterator getMatchingRParen( 972 MacroInfo::tokens_iterator It, 973 MacroInfo::tokens_iterator End); 974 975 /// Retrieves the macro info for \p II refers to at \p Loc. This is important 976 /// because macros can be redefined or undefined. 977 static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP, 978 const SourceManager &SM, 979 const IdentifierInfo *II, 980 SourceLocation Loc); 981 982 //===----------------------------------------------------------------------===// 983 // Definitions of helper functions and methods for expanding macros. 984 //===----------------------------------------------------------------------===// 985 986 static ExpansionInfo 987 getExpandedMacro(SourceLocation MacroLoc, const Preprocessor &PP, 988 const cross_tu::CrossTranslationUnitContext &CTU) { 989 990 const Preprocessor *PPToUse = &PP; 991 if (auto LocAndUnit = CTU.getImportedFromSourceLocation(MacroLoc)) { 992 MacroLoc = LocAndUnit->first; 993 PPToUse = &LocAndUnit->second->getPreprocessor(); 994 } 995 996 llvm::SmallString<200> ExpansionBuf; 997 llvm::raw_svector_ostream OS(ExpansionBuf); 998 TokenPrinter Printer(OS, *PPToUse); 999 llvm::SmallPtrSet<IdentifierInfo*, 8> AlreadyProcessedTokens; 1000 1001 std::string MacroName = getMacroNameAndPrintExpansion( 1002 Printer, MacroLoc, *PPToUse, MacroParamMap{}, AlreadyProcessedTokens); 1003 return {MacroName, std::string(OS.str())}; 1004 } 1005 1006 static std::string getMacroNameAndPrintExpansion( 1007 TokenPrinter &Printer, SourceLocation MacroLoc, const Preprocessor &PP, 1008 const MacroParamMap &PrevParamMap, 1009 llvm::SmallPtrSet<IdentifierInfo *, 8> &AlreadyProcessedTokens) { 1010 1011 const SourceManager &SM = PP.getSourceManager(); 1012 1013 MacroExpansionInfo MExpInfo = 1014 getMacroExpansionInfo(PrevParamMap, SM.getExpansionLoc(MacroLoc), PP); 1015 IdentifierInfo *MacroNameII = PP.getIdentifierInfo(MExpInfo.Name); 1016 1017 // TODO: If the macro definition contains another symbol then this function is 1018 // called recursively. In case this symbol is the one being defined, it will 1019 // be an infinite recursion which is stopped by this "if" statement. However, 1020 // in this case we don't get the full expansion text in the Plist file. See 1021 // the test file where "value" is expanded to "garbage_" instead of 1022 // "garbage_value". 1023 if (!AlreadyProcessedTokens.insert(MacroNameII).second) 1024 return MExpInfo.Name; 1025 1026 if (!MExpInfo.MI) 1027 return MExpInfo.Name; 1028 1029 // Manually expand its arguments from the previous macro. 1030 MExpInfo.ParamMap.expandFromPrevMacro(PrevParamMap); 1031 1032 // Iterate over the macro's tokens and stringify them. 1033 for (auto It = MExpInfo.MI->tokens_begin(), E = MExpInfo.MI->tokens_end(); 1034 It != E; ++It) { 1035 Token T = *It; 1036 1037 // If this token is not an identifier, we only need to print it. 1038 if (T.isNot(tok::identifier)) { 1039 Printer.printToken(T); 1040 continue; 1041 } 1042 1043 const auto *II = T.getIdentifierInfo(); 1044 assert(II && 1045 "This token is an identifier but has no IdentifierInfo!"); 1046 1047 // If this token is a macro that should be expanded inside the current 1048 // macro. 1049 if (getMacroInfoForLocation(PP, SM, II, T.getLocation())) { 1050 getMacroNameAndPrintExpansion(Printer, T.getLocation(), PP, 1051 MExpInfo.ParamMap, AlreadyProcessedTokens); 1052 1053 // If this is a function-like macro, skip its arguments, as 1054 // getExpandedMacro() already printed them. If this is the case, let's 1055 // first jump to the '(' token. 1056 auto N = std::next(It); 1057 if (N != E && N->is(tok::l_paren)) 1058 It = getMatchingRParen(++It, E); 1059 continue; 1060 } 1061 1062 // If this token is the current macro's argument, we should expand it. 1063 auto ParamToArgIt = MExpInfo.ParamMap.find(II); 1064 if (ParamToArgIt != MExpInfo.ParamMap.end()) { 1065 for (MacroInfo::tokens_iterator ArgIt = ParamToArgIt->second.begin(), 1066 ArgEnd = ParamToArgIt->second.end(); 1067 ArgIt != ArgEnd; ++ArgIt) { 1068 1069 // These tokens may still be macros, if that is the case, handle it the 1070 // same way we did above. 1071 const auto *ArgII = ArgIt->getIdentifierInfo(); 1072 if (!ArgII) { 1073 Printer.printToken(*ArgIt); 1074 continue; 1075 } 1076 1077 const auto *MI = PP.getMacroInfo(ArgII); 1078 if (!MI) { 1079 Printer.printToken(*ArgIt); 1080 continue; 1081 } 1082 1083 getMacroNameAndPrintExpansion(Printer, ArgIt->getLocation(), PP, 1084 MExpInfo.ParamMap, 1085 AlreadyProcessedTokens); 1086 // Peek the next token if it is a tok::l_paren. This way we can decide 1087 // if this is the application or just a reference to a function maxro 1088 // symbol: 1089 // 1090 // #define apply(f) ... 1091 // #define func(x) ... 1092 // apply(func) 1093 // apply(func(42)) 1094 auto N = std::next(ArgIt); 1095 if (N != ArgEnd && N->is(tok::l_paren)) 1096 ArgIt = getMatchingRParen(++ArgIt, ArgEnd); 1097 } 1098 continue; 1099 } 1100 1101 // If control reached here, then this token isn't a macro identifier, nor an 1102 // unexpanded macro argument that we need to handle, print it. 1103 Printer.printToken(T); 1104 } 1105 1106 AlreadyProcessedTokens.erase(MacroNameII); 1107 1108 return MExpInfo.Name; 1109 } 1110 1111 static MacroExpansionInfo 1112 getMacroExpansionInfo(const MacroParamMap &PrevParamMap, 1113 SourceLocation ExpanLoc, const Preprocessor &PP) { 1114 1115 const SourceManager &SM = PP.getSourceManager(); 1116 const LangOptions &LangOpts = PP.getLangOpts(); 1117 1118 // First, we create a Lexer to lex *at the expansion location* the tokens 1119 // referring to the macro's name and its arguments. 1120 TokenStream TStream(ExpanLoc, SM, LangOpts); 1121 1122 // Acquire the macro's name. 1123 Token TheTok; 1124 TStream.next(TheTok); 1125 1126 std::string MacroName = PP.getSpelling(TheTok); 1127 1128 const auto *II = PP.getIdentifierInfo(MacroName); 1129 assert(II && "Failed to acquire the IdentifierInfo for the macro!"); 1130 1131 const MacroInfo *MI = getMacroInfoForLocation(PP, SM, II, ExpanLoc); 1132 // assert(MI && "The macro must've been defined at it's expansion location!"); 1133 // 1134 // We should always be able to obtain the MacroInfo in a given TU, but if 1135 // we're running the analyzer with CTU, the Preprocessor won't contain the 1136 // directive history (or anything for that matter) from another TU. 1137 // TODO: assert when we're not running with CTU. 1138 if (!MI) 1139 return { MacroName, MI, {} }; 1140 1141 // Acquire the macro's arguments at the expansion point. 1142 // 1143 // The rough idea here is to lex from the first left parentheses to the last 1144 // right parentheses, and map the macro's parameter to what they will be 1145 // expanded to. A macro argument may contain several token (like '3 + 4'), so 1146 // we'll lex until we find a tok::comma or tok::r_paren, at which point we 1147 // start lexing the next argument or finish. 1148 ArrayRef<const IdentifierInfo *> MacroParams = MI->params(); 1149 if (MacroParams.empty()) 1150 return { MacroName, MI, {} }; 1151 1152 TStream.next(TheTok); 1153 // When this is a token which expands to another macro function then its 1154 // parentheses are not at its expansion locaiton. For example: 1155 // 1156 // #define foo(x) int bar() { return x; } 1157 // #define apply_zero(f) f(0) 1158 // apply_zero(foo) 1159 // ^ 1160 // This is not a tok::l_paren, but foo is a function. 1161 if (TheTok.isNot(tok::l_paren)) 1162 return { MacroName, MI, {} }; 1163 1164 MacroParamMap ParamMap; 1165 1166 // When the argument is a function call, like 1167 // CALL_FN(someFunctionName(param1, param2)) 1168 // we will find tok::l_paren, tok::r_paren, and tok::comma that do not divide 1169 // actual macro arguments, or do not represent the macro argument's closing 1170 // parentheses, so we'll count how many parentheses aren't closed yet. 1171 // If ParanthesesDepth 1172 // * = 0, then there are no more arguments to lex. 1173 // * = 1, then if we find a tok::comma, we can start lexing the next arg. 1174 // * > 1, then tok::comma is a part of the current arg. 1175 int ParenthesesDepth = 1; 1176 1177 // If we encounter the variadic arg, we will lex until the closing 1178 // tok::r_paren, even if we lex a tok::comma and ParanthesesDepth == 1. 1179 const IdentifierInfo *VariadicParamII = PP.getIdentifierInfo("__VA_ARGS__"); 1180 if (MI->isGNUVarargs()) { 1181 // If macro uses GNU-style variadic args, the param name is user-supplied, 1182 // an not "__VA_ARGS__". E.g.: 1183 // #define FOO(a, b, myvargs...) 1184 // In this case, just use the last parameter: 1185 VariadicParamII = *(MacroParams.rbegin()); 1186 } 1187 1188 for (const IdentifierInfo *CurrParamII : MacroParams) { 1189 MacroParamMap::mapped_type ArgTokens; 1190 1191 // One could also simply not supply a single argument to __VA_ARGS__ -- this 1192 // results in a preprocessor warning, but is not an error: 1193 // #define VARIADIC(ptr, ...) \ 1194 // someVariadicTemplateFunction(__VA_ARGS__) 1195 // 1196 // int *ptr; 1197 // VARIADIC(ptr); // Note that there are no commas, this isn't just an 1198 // // empty parameter -- there are no parameters for '...'. 1199 // In any other case, ParenthesesDepth mustn't be 0 here. 1200 if (ParenthesesDepth != 0) { 1201 1202 // Lex the first token of the next macro parameter. 1203 TStream.next(TheTok); 1204 1205 while (CurrParamII == VariadicParamII || ParenthesesDepth != 1 || 1206 !TheTok.is(tok::comma)) { 1207 assert(TheTok.isNot(tok::eof) && 1208 "EOF encountered while looking for expanded macro args!"); 1209 1210 if (TheTok.is(tok::l_paren)) 1211 ++ParenthesesDepth; 1212 1213 if (TheTok.is(tok::r_paren)) 1214 --ParenthesesDepth; 1215 1216 if (ParenthesesDepth == 0) 1217 break; 1218 1219 if (TheTok.is(tok::raw_identifier)) { 1220 PP.LookUpIdentifierInfo(TheTok); 1221 // This token is a variadic parameter: 1222 // 1223 // #define PARAMS_RESOLVE_TO_VA_ARGS(i, fmt) foo(i, fmt); \ 1224 // i = 0; 1225 // #define DISPATCH(...) \ 1226 // PARAMS_RESOLVE_TO_VA_ARGS(__VA_ARGS__); 1227 // // ^~~~~~~~~~~ Variadic parameter here 1228 // 1229 // void multipleParamsResolveToVA_ARGS(void) { 1230 // int x = 1; 1231 // DISPATCH(x, "LF1M healer"); // Multiple arguments are mapped to 1232 // // a single __VA_ARGS__ parameter. 1233 // (void)(10 / x); 1234 // } 1235 // 1236 // We will stumble across this while trying to expand 1237 // PARAMS_RESOLVE_TO_VA_ARGS. By this point, we already noted during 1238 // the processing of DISPATCH what __VA_ARGS__ maps to, so we'll 1239 // retrieve the next series of tokens from that. 1240 if (TheTok.getIdentifierInfo() == VariadicParamII) { 1241 TStream.injectRange(PrevParamMap.at(VariadicParamII)); 1242 TStream.next(TheTok); 1243 continue; 1244 } 1245 } 1246 1247 ArgTokens.push_back(TheTok); 1248 TStream.next(TheTok); 1249 } 1250 } else { 1251 assert(CurrParamII == VariadicParamII && 1252 "No more macro arguments are found, but the current parameter " 1253 "isn't the variadic arg!"); 1254 } 1255 1256 ParamMap.emplace(CurrParamII, std::move(ArgTokens)); 1257 } 1258 1259 assert(TheTok.is(tok::r_paren) && 1260 "Expanded macro argument acquisition failed! After the end of the loop" 1261 " this token should be ')'!"); 1262 1263 return {MacroName, MI, ParamMap}; 1264 } 1265 1266 static MacroInfo::tokens_iterator getMatchingRParen( 1267 MacroInfo::tokens_iterator It, 1268 MacroInfo::tokens_iterator End) { 1269 1270 assert(It->is(tok::l_paren) && "This token should be '('!"); 1271 1272 // Skip until we find the closing ')'. 1273 int ParenthesesDepth = 1; 1274 while (ParenthesesDepth != 0) { 1275 ++It; 1276 1277 assert(It->isNot(tok::eof) && 1278 "Encountered EOF while attempting to skip macro arguments!"); 1279 assert(It != End && 1280 "End of the macro definition reached before finding ')'!"); 1281 1282 if (It->is(tok::l_paren)) 1283 ++ParenthesesDepth; 1284 1285 if (It->is(tok::r_paren)) 1286 --ParenthesesDepth; 1287 } 1288 return It; 1289 } 1290 1291 static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP, 1292 const SourceManager &SM, 1293 const IdentifierInfo *II, 1294 SourceLocation Loc) { 1295 1296 const MacroDirective *MD = PP.getLocalMacroDirectiveHistory(II); 1297 if (!MD) 1298 return nullptr; 1299 1300 return MD->findDirectiveAtLoc(Loc, SM).getMacroInfo(); 1301 } 1302 1303 void MacroParamMap::expandFromPrevMacro(const MacroParamMap &Super) { 1304 1305 for (value_type &Pair : *this) { 1306 ArgTokensTy &CurrArgTokens = Pair.second; 1307 1308 // For each token in the expanded macro argument. 1309 auto It = CurrArgTokens.begin(); 1310 while (It != CurrArgTokens.end()) { 1311 if (It->isNot(tok::identifier)) { 1312 ++It; 1313 continue; 1314 } 1315 1316 const auto *II = It->getIdentifierInfo(); 1317 assert(II); 1318 1319 // Is this an argument that "Super" expands further? 1320 if (!Super.count(II)) { 1321 ++It; 1322 continue; 1323 } 1324 1325 const ArgTokensTy &SuperArgTokens = Super.at(II); 1326 1327 It = CurrArgTokens.insert(It, SuperArgTokens.begin(), 1328 SuperArgTokens.end()); 1329 std::advance(It, SuperArgTokens.size()); 1330 It = CurrArgTokens.erase(It); 1331 } 1332 } 1333 } 1334 1335 void MacroParamMap::dumpToStream(llvm::raw_ostream &Out, 1336 const Preprocessor &PP) const { 1337 for (const std::pair<const IdentifierInfo *, ArgTokensTy> Pair : *this) { 1338 Out << Pair.first->getName() << " -> "; 1339 dumpArgTokensToStream(Out, PP, Pair.second); 1340 Out << '\n'; 1341 } 1342 } 1343 1344 static void dumpArgTokensToStream(llvm::raw_ostream &Out, 1345 const Preprocessor &PP, 1346 const ArgTokensTy &Toks) { 1347 TokenPrinter Printer(Out, PP); 1348 for (Token Tok : Toks) 1349 Printer.printToken(Tok); 1350 } 1351 1352 void TokenPrinter::printToken(const Token &Tok) { 1353 // TODO: Handle GNU extensions where hash and hashhash occurs right before 1354 // __VA_ARGS__. 1355 // cppreference.com: "some compilers offer an extension that allows ## to 1356 // appear after a comma and before __VA_ARGS__, in which case the ## does 1357 // nothing when the variable arguments are present, but removes the comma when 1358 // the variable arguments are not present: this makes it possible to define 1359 // macros such as fprintf (stderr, format, ##__VA_ARGS__)" 1360 // FIXME: Handle named variadic macro parameters (also a GNU extension). 1361 1362 // If this is the first token to be printed, don't print space. 1363 if (PrevTok.isNot(tok::unknown)) { 1364 // If the tokens were already space separated, or if they must be to avoid 1365 // them being implicitly pasted, add a space between them. 1366 if(Tok.hasLeadingSpace() || ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, 1367 Tok)) { 1368 // AvoidConcat doesn't check for ##, don't print a space around it. 1369 if (PrevTok.isNot(tok::hashhash) && Tok.isNot(tok::hashhash)) { 1370 OS << ' '; 1371 } 1372 } 1373 } 1374 1375 if (!Tok.isOneOf(tok::hash, tok::hashhash)) { 1376 if (PrevTok.is(tok::hash)) 1377 OS << '\"' << PP.getSpelling(Tok) << '\"'; 1378 else 1379 OS << PP.getSpelling(Tok); 1380 } 1381 1382 PrevPrevTok = PrevTok; 1383 PrevTok = Tok; 1384 } 1385