19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/None.h"
22 #include "llvm/ADT/SmallString.h"
23 #include "llvm/ADT/SmallVector.h"
24 #include "llvm/ADT/StringRef.h"
25 #include "llvm/Support/raw_ostream.h"
31 using namespace clang;
35 : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
46 : MergedFixits(MergedFixits) {}
63 for (
const auto &Hint : FixItHints)
64 if (Hint.CodeToInsert.empty()) {
65 if (Hint.InsertFromRange.isValid())
67 Hint.InsertFromRange,
false,
68 Hint.BeforePreviousInsertions);
70 commit.
remove(Hint.RemoveRange);
72 if (Hint.RemoveRange.isTokenRange() ||
73 Hint.RemoveRange.getBegin() != Hint.RemoveRange.getEnd())
74 commit.
replace(Hint.RemoveRange, Hint.CodeToInsert);
76 commit.
insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert,
77 false, Hint.BeforePreviousInsertions);
81 if (Editor.
commit(commit)) {
82 FixitReceiver Rec(MergedFixits);
106 if (!FixItHints.empty()) {
108 FixItHints = MergedFixits;
111 for (
const auto &Hint : FixItHints)
112 if (Hint.RemoveRange.isValid())
113 MutableRanges.push_back(Hint.RemoveRange);
124 emitIncludeStack(Loc, PLoc,
Level);
128 emitCaret(Loc,
Level, MutableRanges, FixItHints);
133 emitMacroExpansions(UnexpandedLoc,
Level, MutableRanges, FixItHints);
149 void DiagnosticRenderer::emitBasicNote(StringRef Message) {
181 emitIncludeStackRecursively(IncludeLoc);
184 emitImportStack(Loc);
190 void DiagnosticRenderer::emitIncludeStackRecursively(
FullSourceLoc Loc) {
204 if (!Imported.second.empty()) {
206 emitImportStackRecursively(Imported.first, Imported.second);
211 emitIncludeStackRecursively(
219 void DiagnosticRenderer::emitImportStack(
FullSourceLoc Loc) {
226 emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second);
231 void DiagnosticRenderer::emitImportStackRecursively(
FullSourceLoc Loc,
232 StringRef ModuleName) {
233 if (ModuleName.empty()) {
241 emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second);
249 void DiagnosticRenderer::emitModuleBuildStack(
const SourceManager &
SM) {
251 for (
const auto &I : Stack) {
265 bool &IsTokenRange) {
266 assert(
SM->getFileID(Loc) == MacroFileID);
267 if (MacroFileID == CaretFileID)
274 if (
SM->isMacroArgExpansion(Loc)) {
277 if (std::binary_search(CommonArgExpansions.begin(),
278 CommonArgExpansions.end(), MacroFileID))
281 MacroArgRange =
SM->getImmediateExpansionRange(Loc);
283 MacroRange =
SM->getImmediateExpansionRange(Loc);
291 MacroFileID =
SM->getFileID(MacroLocation);
292 bool TokenRange = IsBegin ? IsTokenRange : MacroRange.
isTokenRange();
295 CommonArgExpansions, IsBegin,
SM, TokenRange);
297 IsTokenRange = TokenRange;
298 return MacroLocation;
309 MacroFileID =
SM->getFileID(MacroArgLocation);
311 CommonArgExpansions, IsBegin,
SM, IsTokenRange);
320 if (
SM->isMacroArgExpansion(Loc)) {
321 IDs.push_back(
SM->getFileID(Loc));
322 Loc =
SM->getImmediateSpellingLoc(Loc);
324 auto ExpRange =
SM->getImmediateExpansionRange(Loc);
325 Loc = IsBegin ? ExpRange.getBegin() : ExpRange.getEnd();
339 llvm::sort(BeginArgExpansions);
340 llvm::sort(EndArgExpansions);
341 std::set_intersection(BeginArgExpansions.begin(), BeginArgExpansions.end(),
342 EndArgExpansions.begin(), EndArgExpansions.end(),
343 std::back_inserter(CommonArgExpansions));
363 for (
const auto &Range : Ranges) {
364 if (Range.isInvalid())
368 bool IsTokenRange = Range.isTokenRange();
376 llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap;
378 BeginLocsMap[BeginFileID] =
Begin;
379 Begin =
SM->getImmediateExpansionRange(
Begin).getBegin();
380 BeginFileID =
SM->getFileID(
Begin);
384 if (BeginFileID != EndFileID) {
385 while (
End.
isMacroID() && !BeginLocsMap.count(EndFileID)) {
386 auto Exp =
SM->getImmediateExpansionRange(
End);
387 IsTokenRange = Exp.isTokenRange();
389 EndFileID =
SM->getFileID(
End);
392 Begin = BeginLocsMap[EndFileID];
393 BeginFileID = EndFileID;
408 CommonArgExpansions,
true,
SM,
411 CommonArgExpansions,
false,
SM,
435 void DiagnosticRenderer::emitSingleMacroExpansion(
447 llvm::raw_svector_ostream
Message(MessageStorage);
450 if (MacroName.empty())
451 Message <<
"expanded from here";
453 Message <<
"expanded from macro '" << MacroName <<
"'";
456 SpellingRanges, None);
466 if (
SM.isMacroArgExpansion(Loc, &MacroLoc)) {
467 if (ArgumentLoc == MacroLoc)
return true;
478 SourceLocation BegLoc = Range.getBegin(), EndLoc = Range.getEnd();
479 while (BegLoc != EndLoc) {
492 assert(Loc.
isMacroID() &&
"Must be a macro expansion!");
498 unsigned ValidCount = 0;
499 for (
const auto &Range : Ranges)
503 if (ValidCount > SpellingRanges.size())
514 for (
const auto &Range : SpellingRanges)
532 void DiagnosticRenderer::emitMacroExpansions(
FullSourceLoc Loc,
536 assert(Loc.
isValid() &&
"must have a valid source location here");
542 unsigned IgnoredEnd = 0;
546 if (
SM.isMacroArgExpansion(L))
547 LocationStack.push_back(
SM.getImmediateExpansionRange(L).getBegin());
549 LocationStack.push_back(L);
552 IgnoredEnd = LocationStack.size();
554 L =
SM.getImmediateMacroCallerLoc(L);
560 L =
SM.getImmediateMacroCallerLoc(LocationStack.back());
561 assert(L.
isValid() &&
"must have a valid source location here");
564 LocationStack.erase(LocationStack.begin(),
565 LocationStack.begin() + IgnoredEnd);
567 unsigned MacroDepth = LocationStack.size();
568 unsigned MacroLimit =
DiagOpts->MacroBacktraceLimit;
569 if (MacroDepth <= MacroLimit || MacroLimit == 0) {
570 for (
auto I = LocationStack.rbegin(), E = LocationStack.rend();
576 unsigned MacroStartMessages = MacroLimit / 2;
577 unsigned MacroEndMessages = MacroLimit / 2 + MacroLimit % 2;
579 for (
auto I = LocationStack.rbegin(),
580 E = LocationStack.rbegin() + MacroStartMessages;
585 llvm::raw_svector_ostream
Message(MessageStorage);
586 Message <<
"(skipping " << (MacroDepth - MacroLimit)
587 <<
" expansions in backtrace; use -fmacro-backtrace-limit=0 to "
591 for (
auto I = LocationStack.rend() - MacroEndMessages,
592 E = LocationStack.rend();
603 llvm::raw_svector_ostream Message(MessageStorage);
604 Message <<
"in file included from " << PLoc.
getFilename() <<
':'
611 StringRef ModuleName) {
614 llvm::raw_svector_ostream Message(MessageStorage);
615 Message <<
"in module '" << ModuleName;
617 Message <<
"' imported from " << PLoc.
getFilename() <<
':'
625 StringRef ModuleName) {
628 llvm::raw_svector_ostream Message(MessageStorage);
630 Message <<
"while building module '" << ModuleName <<
"' imported from "
633 Message <<
"while building module '" << ModuleName <<
"':";