DiagnosticRenderer.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. //===--- DiagnosticRenderer.cpp - Diagnostic Pretty-Printing --------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "clang/Frontend/DiagnosticRenderer.h"
  10. #include "clang/Basic/DiagnosticOptions.h"
  11. #include "clang/Basic/FileManager.h"
  12. #include "clang/Basic/SourceManager.h"
  13. #include "clang/Edit/Commit.h"
  14. #include "clang/Edit/EditedSource.h"
  15. #include "clang/Edit/EditsReceiver.h"
  16. #include "clang/Lex/Lexer.h"
  17. #include "llvm/ADT/SmallSet.h"
  18. #include "llvm/ADT/SmallString.h"
  19. #include "llvm/Support/ErrorHandling.h"
  20. #include "llvm/Support/MemoryBuffer.h"
  21. #include "llvm/Support/raw_ostream.h"
  22. #include <algorithm>
  23. using namespace clang;
  24. /// \brief Retrieve the name of the immediate macro expansion.
  25. ///
  26. /// This routine starts from a source location, and finds the name of the macro
  27. /// responsible for its immediate expansion. It looks through any intervening
  28. /// macro argument expansions to compute this. It returns a StringRef which
  29. /// refers to the SourceManager-owned buffer of the source where that macro
  30. /// name is spelled. Thus, the result shouldn't out-live that SourceManager.
  31. ///
  32. /// This differs from Lexer::getImmediateMacroName in that any macro argument
  33. /// location will result in the topmost function macro that accepted it.
  34. /// e.g.
  35. /// \code
  36. /// MAC1( MAC2(foo) )
  37. /// \endcode
  38. /// for location of 'foo' token, this function will return "MAC1" while
  39. /// Lexer::getImmediateMacroName will return "MAC2".
  40. static StringRef getImmediateMacroName(SourceLocation Loc,
  41. const SourceManager &SM,
  42. const LangOptions &LangOpts) {
  43. assert(Loc.isMacroID() && "Only reasonble to call this on macros");
  44. // Walk past macro argument expanions.
  45. while (SM.isMacroArgExpansion(Loc))
  46. Loc = SM.getImmediateExpansionRange(Loc).first;
  47. // If the macro's spelling has no FileID, then it's actually a token paste
  48. // or stringization (or similar) and not a macro at all.
  49. if (!SM.getFileEntryForID(SM.getFileID(SM.getSpellingLoc(Loc))))
  50. return StringRef();
  51. // Find the spelling location of the start of the non-argument expansion
  52. // range. This is where the macro name was spelled in order to begin
  53. // expanding this macro.
  54. Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first);
  55. // Dig out the buffer where the macro name was spelled and the extents of the
  56. // name so that we can render it into the expansion note.
  57. std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc);
  58. unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts);
  59. StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first);
  60. return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength);
  61. }
  62. DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts,
  63. DiagnosticOptions *DiagOpts)
  64. : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
  65. DiagnosticRenderer::~DiagnosticRenderer() {}
  66. namespace {
  67. class FixitReceiver : public edit::EditsReceiver {
  68. SmallVectorImpl<FixItHint> &MergedFixits;
  69. public:
  70. FixitReceiver(SmallVectorImpl<FixItHint> &MergedFixits)
  71. : MergedFixits(MergedFixits) { }
  72. void insert(SourceLocation loc, StringRef text) override {
  73. MergedFixits.push_back(FixItHint::CreateInsertion(loc, text));
  74. }
  75. void replace(CharSourceRange range, StringRef text) override {
  76. MergedFixits.push_back(FixItHint::CreateReplacement(range, text));
  77. }
  78. };
  79. }
  80. static void mergeFixits(ArrayRef<FixItHint> FixItHints,
  81. const SourceManager &SM, const LangOptions &LangOpts,
  82. SmallVectorImpl<FixItHint> &MergedFixits) {
  83. edit::Commit commit(SM, LangOpts);
  84. for (ArrayRef<FixItHint>::const_iterator
  85. I = FixItHints.begin(), E = FixItHints.end(); I != E; ++I) {
  86. const FixItHint &Hint = *I;
  87. if (Hint.CodeToInsert.empty()) {
  88. if (Hint.InsertFromRange.isValid())
  89. commit.insertFromRange(Hint.RemoveRange.getBegin(),
  90. Hint.InsertFromRange, /*afterToken=*/false,
  91. Hint.BeforePreviousInsertions);
  92. else
  93. commit.remove(Hint.RemoveRange);
  94. } else {
  95. if (Hint.RemoveRange.isTokenRange() ||
  96. Hint.RemoveRange.getBegin() != Hint.RemoveRange.getEnd())
  97. commit.replace(Hint.RemoveRange, Hint.CodeToInsert);
  98. else
  99. commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert,
  100. /*afterToken=*/false, Hint.BeforePreviousInsertions);
  101. }
  102. }
  103. edit::EditedSource Editor(SM, LangOpts);
  104. if (Editor.commit(commit)) {
  105. FixitReceiver Rec(MergedFixits);
  106. Editor.applyRewrites(Rec);
  107. }
  108. }
  109. void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
  110. DiagnosticsEngine::Level Level,
  111. StringRef Message,
  112. ArrayRef<CharSourceRange> Ranges,
  113. ArrayRef<FixItHint> FixItHints,
  114. const SourceManager *SM,
  115. DiagOrStoredDiag D) {
  116. assert(SM || Loc.isInvalid());
  117. beginDiagnostic(D, Level);
  118. if (!Loc.isValid())
  119. // If we have no source location, just emit the diagnostic message.
  120. emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, SM, D);
  121. else {
  122. // Get the ranges into a local array we can hack on.
  123. SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(),
  124. Ranges.end());
  125. SmallVector<FixItHint, 8> MergedFixits;
  126. if (!FixItHints.empty()) {
  127. mergeFixits(FixItHints, *SM, LangOpts, MergedFixits);
  128. FixItHints = MergedFixits;
  129. }
  130. for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(),
  131. E = FixItHints.end();
  132. I != E; ++I)
  133. if (I->RemoveRange.isValid())
  134. MutableRanges.push_back(I->RemoveRange);
  135. SourceLocation UnexpandedLoc = Loc;
  136. // Find the ultimate expansion location for the diagnostic.
  137. Loc = SM->getFileLoc(Loc);
  138. PresumedLoc PLoc = SM->getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
  139. // First, if this diagnostic is not in the main file, print out the
  140. // "included from" lines.
  141. emitIncludeStack(Loc, PLoc, Level, *SM);
  142. // Next, emit the actual diagnostic message and caret.
  143. emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D);
  144. emitCaret(Loc, Level, MutableRanges, FixItHints, *SM);
  145. // If this location is within a macro, walk from UnexpandedLoc up to Loc
  146. // and produce a macro backtrace.
  147. if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) {
  148. unsigned MacroDepth = 0;
  149. emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM,
  150. MacroDepth);
  151. }
  152. }
  153. LastLoc = Loc;
  154. LastLevel = Level;
  155. endDiagnostic(D, Level);
  156. }
  157. void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
  158. emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
  159. Diag.getRanges(), Diag.getFixIts(),
  160. Diag.getLocation().isValid() ? &Diag.getLocation().getManager()
  161. : nullptr,
  162. &Diag);
  163. }
  164. void DiagnosticRenderer::emitBasicNote(StringRef Message) {
  165. emitDiagnosticMessage(
  166. SourceLocation(), PresumedLoc(), DiagnosticsEngine::Note, Message,
  167. ArrayRef<CharSourceRange>(), nullptr, DiagOrStoredDiag());
  168. }
  169. /// \brief Prints an include stack when appropriate for a particular
  170. /// diagnostic level and location.
  171. ///
  172. /// This routine handles all the logic of suppressing particular include
  173. /// stacks (such as those for notes) and duplicate include stacks when
  174. /// repeated warnings occur within the same file. It also handles the logic
  175. /// of customizing the formatting and display of the include stack.
  176. ///
  177. /// \param Loc The diagnostic location.
  178. /// \param PLoc The presumed location of the diagnostic location.
  179. /// \param Level The diagnostic level of the message this stack pertains to.
  180. void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
  181. PresumedLoc PLoc,
  182. DiagnosticsEngine::Level Level,
  183. const SourceManager &SM) {
  184. SourceLocation IncludeLoc = PLoc.getIncludeLoc();
  185. // Skip redundant include stacks altogether.
  186. if (LastIncludeLoc == IncludeLoc)
  187. return;
  188. LastIncludeLoc = IncludeLoc;
  189. if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note)
  190. return;
  191. if (IncludeLoc.isValid())
  192. emitIncludeStackRecursively(IncludeLoc, SM);
  193. else {
  194. emitModuleBuildStack(SM);
  195. emitImportStack(Loc, SM);
  196. }
  197. }
  198. /// \brief Helper to recursivly walk up the include stack and print each layer
  199. /// on the way back down.
  200. void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc,
  201. const SourceManager &SM) {
  202. if (Loc.isInvalid()) {
  203. emitModuleBuildStack(SM);
  204. return;
  205. }
  206. PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
  207. if (PLoc.isInvalid())
  208. return;
  209. // If this source location was imported from a module, print the module
  210. // import stack rather than the
  211. // FIXME: We want submodule granularity here.
  212. std::pair<SourceLocation, StringRef> Imported = SM.getModuleImportLoc(Loc);
  213. if (Imported.first.isValid()) {
  214. // This location was imported by a module. Emit the module import stack.
  215. emitImportStackRecursively(Imported.first, Imported.second, SM);
  216. return;
  217. }
  218. // Emit the other include frames first.
  219. emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM);
  220. // Emit the inclusion text/note.
  221. emitIncludeLocation(Loc, PLoc, SM);
  222. }
  223. /// \brief Emit the module import stack associated with the current location.
  224. void DiagnosticRenderer::emitImportStack(SourceLocation Loc,
  225. const SourceManager &SM) {
  226. if (Loc.isInvalid()) {
  227. emitModuleBuildStack(SM);
  228. return;
  229. }
  230. std::pair<SourceLocation, StringRef> NextImportLoc
  231. = SM.getModuleImportLoc(Loc);
  232. emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM);
  233. }
  234. /// \brief Helper to recursivly walk up the import stack and print each layer
  235. /// on the way back down.
  236. void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc,
  237. StringRef ModuleName,
  238. const SourceManager &SM) {
  239. if (Loc.isInvalid()) {
  240. return;
  241. }
  242. PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
  243. if (PLoc.isInvalid())
  244. return;
  245. // Emit the other import frames first.
  246. std::pair<SourceLocation, StringRef> NextImportLoc
  247. = SM.getModuleImportLoc(Loc);
  248. emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM);
  249. // Emit the inclusion text/note.
  250. emitImportLocation(Loc, PLoc, ModuleName, SM);
  251. }
  252. /// \brief Emit the module build stack, for cases where a module is (re-)built
  253. /// on demand.
  254. void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) {
  255. ModuleBuildStack Stack = SM.getModuleBuildStack();
  256. for (unsigned I = 0, N = Stack.size(); I != N; ++I) {
  257. const SourceManager &CurSM = Stack[I].second.getManager();
  258. SourceLocation CurLoc = Stack[I].second;
  259. emitBuildingModuleLocation(CurLoc,
  260. CurSM.getPresumedLoc(CurLoc,
  261. DiagOpts->ShowPresumedLoc),
  262. Stack[I].first,
  263. CurSM);
  264. }
  265. }
  266. // Helper function to fix up source ranges. It takes in an array of ranges,
  267. // and outputs an array of ranges where we want to draw the range highlighting
  268. // around the location specified by CaretLoc.
  269. //
  270. // To find locations which correspond to the caret, we crawl the macro caller
  271. // chain for the beginning and end of each range. If the caret location
  272. // is in a macro expansion, we search each chain for a location
  273. // in the same expansion as the caret; otherwise, we crawl to the top of
  274. // each chain. Two locations are part of the same macro expansion
  275. // iff the FileID is the same.
  276. static void mapDiagnosticRanges(
  277. SourceLocation CaretLoc,
  278. ArrayRef<CharSourceRange> Ranges,
  279. SmallVectorImpl<CharSourceRange> &SpellingRanges,
  280. const SourceManager *SM) {
  281. FileID CaretLocFileID = SM->getFileID(CaretLoc);
  282. for (ArrayRef<CharSourceRange>::const_iterator I = Ranges.begin(),
  283. E = Ranges.end();
  284. I != E; ++I) {
  285. SourceLocation Begin = I->getBegin(), End = I->getEnd();
  286. bool IsTokenRange = I->isTokenRange();
  287. FileID BeginFileID = SM->getFileID(Begin);
  288. FileID EndFileID = SM->getFileID(End);
  289. // Find the common parent for the beginning and end of the range.
  290. // First, crawl the expansion chain for the beginning of the range.
  291. llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap;
  292. while (Begin.isMacroID() && BeginFileID != EndFileID) {
  293. BeginLocsMap[BeginFileID] = Begin;
  294. Begin = SM->getImmediateExpansionRange(Begin).first;
  295. BeginFileID = SM->getFileID(Begin);
  296. }
  297. // Then, crawl the expansion chain for the end of the range.
  298. if (BeginFileID != EndFileID) {
  299. while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) {
  300. End = SM->getImmediateExpansionRange(End).second;
  301. EndFileID = SM->getFileID(End);
  302. }
  303. if (End.isMacroID()) {
  304. Begin = BeginLocsMap[EndFileID];
  305. BeginFileID = EndFileID;
  306. }
  307. }
  308. while (Begin.isMacroID() && BeginFileID != CaretLocFileID) {
  309. if (SM->isMacroArgExpansion(Begin)) {
  310. Begin = SM->getImmediateSpellingLoc(Begin);
  311. End = SM->getImmediateSpellingLoc(End);
  312. } else {
  313. Begin = SM->getImmediateExpansionRange(Begin).first;
  314. End = SM->getImmediateExpansionRange(End).second;
  315. }
  316. BeginFileID = SM->getFileID(Begin);
  317. if (BeginFileID != SM->getFileID(End)) {
  318. // FIXME: Ugly hack to stop a crash; this code is making bad
  319. // assumptions and it's too complicated for me to reason
  320. // about.
  321. Begin = End = SourceLocation();
  322. break;
  323. }
  324. }
  325. // Return the spelling location of the beginning and end of the range.
  326. Begin = SM->getSpellingLoc(Begin);
  327. End = SM->getSpellingLoc(End);
  328. SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End),
  329. IsTokenRange));
  330. }
  331. }
  332. void DiagnosticRenderer::emitCaret(SourceLocation Loc,
  333. DiagnosticsEngine::Level Level,
  334. ArrayRef<CharSourceRange> Ranges,
  335. ArrayRef<FixItHint> Hints,
  336. const SourceManager &SM) {
  337. SmallVector<CharSourceRange, 4> SpellingRanges;
  338. mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
  339. emitCodeContext(Loc, Level, SpellingRanges, Hints, SM);
  340. }
  341. /// \brief Recursively emit notes for each macro expansion and caret
  342. /// diagnostics where appropriate.
  343. ///
  344. /// Walks up the macro expansion stack printing expansion notes, the code
  345. /// snippet, caret, underlines and FixItHint display as appropriate at each
  346. /// level.
  347. ///
  348. /// \param Loc The location for this caret.
  349. /// \param Level The diagnostic level currently being emitted.
  350. /// \param Ranges The underlined ranges for this code snippet.
  351. /// \param Hints The FixIt hints active for this diagnostic.
  352. /// \param OnMacroInst The current depth of the macro expansion stack.
  353. void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc,
  354. DiagnosticsEngine::Level Level,
  355. ArrayRef<CharSourceRange> Ranges,
  356. ArrayRef<FixItHint> Hints,
  357. const SourceManager &SM,
  358. unsigned &MacroDepth,
  359. unsigned OnMacroInst) {
  360. assert(!Loc.isInvalid() && "must have a valid source location here");
  361. // Walk up to the caller of this macro, and produce a backtrace down to there.
  362. SourceLocation OneLevelUp = SM.getImmediateMacroCallerLoc(Loc);
  363. if (OneLevelUp.isMacroID())
  364. emitMacroExpansions(OneLevelUp, Level, Ranges, Hints, SM,
  365. MacroDepth, OnMacroInst + 1);
  366. else
  367. MacroDepth = OnMacroInst + 1;
  368. unsigned MacroSkipStart = 0, MacroSkipEnd = 0;
  369. if (MacroDepth > DiagOpts->MacroBacktraceLimit &&
  370. DiagOpts->MacroBacktraceLimit != 0) {
  371. MacroSkipStart = DiagOpts->MacroBacktraceLimit / 2 +
  372. DiagOpts->MacroBacktraceLimit % 2;
  373. MacroSkipEnd = MacroDepth - DiagOpts->MacroBacktraceLimit / 2;
  374. }
  375. // Whether to suppress printing this macro expansion.
  376. bool Suppressed = (OnMacroInst >= MacroSkipStart &&
  377. OnMacroInst < MacroSkipEnd);
  378. if (Suppressed) {
  379. // Tell the user that we've skipped contexts.
  380. if (OnMacroInst == MacroSkipStart) {
  381. SmallString<200> MessageStorage;
  382. llvm::raw_svector_ostream Message(MessageStorage);
  383. Message << "(skipping " << (MacroSkipEnd - MacroSkipStart)
  384. << " expansions in backtrace; use -fmacro-backtrace-limit=0 to "
  385. "see all)";
  386. emitBasicNote(Message.str());
  387. }
  388. return;
  389. }
  390. // Find the spelling location for the macro definition. We must use the
  391. // spelling location here to avoid emitting a macro bactrace for the note.
  392. SourceLocation SpellingLoc = Loc;
  393. // If this is the expansion of a macro argument, point the caret at the
  394. // use of the argument in the definition of the macro, not the expansion.
  395. if (SM.isMacroArgExpansion(Loc))
  396. SpellingLoc = SM.getImmediateExpansionRange(Loc).first;
  397. SpellingLoc = SM.getSpellingLoc(SpellingLoc);
  398. // Map the ranges into the FileID of the diagnostic location.
  399. SmallVector<CharSourceRange, 4> SpellingRanges;
  400. mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
  401. SmallString<100> MessageStorage;
  402. llvm::raw_svector_ostream Message(MessageStorage);
  403. StringRef MacroName = getImmediateMacroName(Loc, SM, LangOpts);
  404. if (MacroName.empty())
  405. Message << "expanded from here";
  406. else
  407. Message << "expanded from macro '" << MacroName << "'";
  408. emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(),
  409. SpellingRanges, None, &SM);
  410. }
  411. DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {}
  412. void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc,
  413. PresumedLoc PLoc,
  414. const SourceManager &SM) {
  415. // Generate a note indicating the include location.
  416. SmallString<200> MessageStorage;
  417. llvm::raw_svector_ostream Message(MessageStorage);
  418. Message << "in file included from " << PLoc.getFilename() << ':'
  419. << PLoc.getLine() << ":";
  420. emitNote(Loc, Message.str(), &SM);
  421. }
  422. void DiagnosticNoteRenderer::emitImportLocation(SourceLocation Loc,
  423. PresumedLoc PLoc,
  424. StringRef ModuleName,
  425. const SourceManager &SM) {
  426. // Generate a note indicating the include location.
  427. SmallString<200> MessageStorage;
  428. llvm::raw_svector_ostream Message(MessageStorage);
  429. Message << "in module '" << ModuleName << "' imported from "
  430. << PLoc.getFilename() << ':' << PLoc.getLine() << ":";
  431. emitNote(Loc, Message.str(), &SM);
  432. }
  433. void
  434. DiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc,
  435. PresumedLoc PLoc,
  436. StringRef ModuleName,
  437. const SourceManager &SM) {
  438. // Generate a note indicating the include location.
  439. SmallString<200> MessageStorage;
  440. llvm::raw_svector_ostream Message(MessageStorage);
  441. if (PLoc.getFilename())
  442. Message << "while building module '" << ModuleName << "' imported from "
  443. << PLoc.getFilename() << ':' << PLoc.getLine() << ":";
  444. else
  445. Message << "while building module '" << ModuleName << "':";
  446. emitNote(Loc, Message.str(), &SM);
  447. }