diff options
author | Ted Kremenek <kremenek@apple.com> | 2011-12-17 05:26:04 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2011-12-17 05:26:04 +0000 |
commit | 2898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75 (patch) | |
tree | be41824d2640dc49bab6971470b099cb1a914e37 /lib | |
parent | 373cb7832090dd5a380be73fdff79881721eed00 (diff) |
Refactor 'TextDiagnostic' to have a parent class 'DiagnosticRenderer' which handles
the policy of how diagnostics are lowered/rendered, while TextDiagnostic handles
the actual pretty-printing.
This is a first part of reworking SerializedDiagnosticPrinter to use the same
inclusion-stack/macro-expansion logic as TextDiagnostic.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146819 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Frontend/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Frontend/DiagnosticRenderer.cpp | 297 | ||||
-rw-r--r-- | lib/Frontend/TextDiagnostic.cpp | 284 |
3 files changed, 322 insertions, 260 deletions
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index f76b79566c..f98ed11c67 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -18,6 +18,7 @@ add_clang_library(clangFrontend CompilerInvocation.cpp CreateInvocationFromCommandLine.cpp DependencyFile.cpp + DiagnosticRenderer.cpp FrontendAction.cpp FrontendActions.cpp FrontendOptions.cpp diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp new file mode 100644 index 0000000000..293ffb7a4e --- /dev/null +++ b/lib/Frontend/DiagnosticRenderer.cpp @@ -0,0 +1,297 @@ +//===--- DiagnosticRenderer.cpp - Diagnostic Pretty-Printing --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/DiagnosticRenderer.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Frontend/DiagnosticOptions.h" +#include "clang/Lex/Lexer.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/SmallString.h" +#include <algorithm> +using namespace clang; + +/// Look through spelling locations for a macro argument expansion, and +/// if found skip to it so that we can trace the argument rather than the macros +/// in which that argument is used. If no macro argument expansion is found, +/// don't skip anything and return the starting location. +static SourceLocation skipToMacroArgExpansion(const SourceManager &SM, + SourceLocation StartLoc) { + for (SourceLocation L = StartLoc; L.isMacroID(); + L = SM.getImmediateSpellingLoc(L)) { + if (SM.isMacroArgExpansion(L)) + return L; + } + + // Otherwise just return initial location, there's nothing to skip. + return StartLoc; +} + +/// Gets the location of the immediate macro caller, one level up the stack +/// toward the initial macro typed into the source. +static SourceLocation getImmediateMacroCallerLoc(const SourceManager &SM, + SourceLocation Loc) { + if (!Loc.isMacroID()) return Loc; + + // When we have the location of (part of) an expanded parameter, its spelling + // location points to the argument as typed into the macro call, and + // therefore is used to locate the macro caller. + if (SM.isMacroArgExpansion(Loc)) + return SM.getImmediateSpellingLoc(Loc); + + // Otherwise, the caller of the macro is located where this macro is + // expanded (while the spelling is part of the macro definition). + return SM.getImmediateExpansionRange(Loc).first; +} + +/// Gets the location of the immediate macro callee, one level down the stack +/// toward the leaf macro. +static SourceLocation getImmediateMacroCalleeLoc(const SourceManager &SM, + SourceLocation Loc) { + if (!Loc.isMacroID()) return Loc; + + // When we have the location of (part of) an expanded parameter, its + // expansion location points to the unexpanded paramater reference within + // the macro definition (or callee). + if (SM.isMacroArgExpansion(Loc)) + return SM.getImmediateExpansionRange(Loc).first; + + // Otherwise, the callee of the macro is located where this location was + // spelled inside the macro definition. + return SM.getImmediateSpellingLoc(Loc); +} + +/// \brief Retrieve the name of the immediate macro expansion. +/// +/// This routine starts from a source location, and finds the name of the macro +/// responsible for its immediate expansion. It looks through any intervening +/// macro argument expansions to compute this. It returns a StringRef which +/// refers to the SourceManager-owned buffer of the source where that macro +/// name is spelled. Thus, the result shouldn't out-live that SourceManager. +/// +static StringRef getImmediateMacroName(SourceLocation Loc, + const SourceManager &SM, + const LangOptions &LangOpts) { + assert(Loc.isMacroID() && "Only reasonble to call this on macros"); + // Walk past macro argument expanions. + while (SM.isMacroArgExpansion(Loc)) + Loc = SM.getImmediateExpansionRange(Loc).first; + + // Find the spelling location of the start of the non-argument expansion + // range. This is where the macro name was spelled in order to begin + // expanding this macro. + Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first); + + // Dig out the buffer where the macro name was spelled and the extents of the + // name so that we can render it into the expansion note. + std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc); + unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts); + StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first); + return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength); +} + +/// Get the presumed location of a diagnostic message. This computes the +/// presumed location for the top of any macro backtrace when present. +static PresumedLoc getDiagnosticPresumedLoc(const SourceManager &SM, + SourceLocation Loc) { + // This is a condensed form of the algorithm used by emitCaretDiagnostic to + // walk to the top of the macro call stack. + while (Loc.isMacroID()) { + Loc = skipToMacroArgExpansion(SM, Loc); + Loc = getImmediateMacroCallerLoc(SM, Loc); + } + + return SM.getPresumedLoc(Loc); +} + +DiagnosticRenderer::DiagnosticRenderer(const SourceManager &SM, + const LangOptions &LangOpts, + const DiagnosticOptions &DiagOpts) +: SM(SM), LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {} + +DiagnosticRenderer::~DiagnosticRenderer() {} + + +void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, + DiagnosticsEngine::Level Level, + StringRef Message, + ArrayRef<CharSourceRange> Ranges, + ArrayRef<FixItHint> FixItHints, + const Diagnostic *Info) { + + beginDiagnostic(Info, Level); + + PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, Loc); + + // First, if this diagnostic is not in the main file, print out the + // "included from" lines. + emitIncludeStack(PLoc.getIncludeLoc(), Level); + + // Next, emit the actual diagnostic message. + emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, Info); + + // Only recurse if we have a valid location. + if (Loc.isValid()) { + // Get the ranges into a local array we can hack on. + SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(), + Ranges.end()); + + for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(), + E = FixItHints.end(); + I != E; ++I) + if (I->RemoveRange.isValid()) + MutableRanges.push_back(I->RemoveRange); + + unsigned MacroDepth = 0; + emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints, + MacroDepth); + } + + LastLoc = Loc; + LastLevel = Level; + + endDiagnostic(Info, Level); +} + +/// \brief Prints an include stack when appropriate for a particular +/// diagnostic level and location. +/// +/// This routine handles all the logic of suppressing particular include +/// stacks (such as those for notes) and duplicate include stacks when +/// repeated warnings occur within the same file. It also handles the logic +/// of customizing the formatting and display of the include stack. +/// +/// \param Level The diagnostic level of the message this stack pertains to. +/// \param Loc The include location of the current file (not the diagnostic +/// location). +void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, + DiagnosticsEngine::Level Level) { + // Skip redundant include stacks altogether. + if (LastIncludeLoc == Loc) + return; + LastIncludeLoc = Loc; + + if (!DiagOpts.ShowNoteIncludeStack && Level == DiagnosticsEngine::Note) + return; + + emitIncludeStackRecursively(Loc); +} + +/// \brief Helper to recursivly walk up the include stack and print each layer +/// on the way back down. +void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc) { + if (Loc.isInvalid()) + return; + + PresumedLoc PLoc = SM.getPresumedLoc(Loc); + if (PLoc.isInvalid()) + return; + + // Emit the other include frames first. + emitIncludeStackRecursively(PLoc.getIncludeLoc()); + + // Emit the inclusion text/note. + emitIncludeLocation(Loc, PLoc); +} + +/// \brief Recursively emit notes for each macro expansion and caret +/// diagnostics where appropriate. +/// +/// Walks up the macro expansion stack printing expansion notes, the code +/// snippet, caret, underlines and FixItHint display as appropriate at each +/// level. +/// +/// \param Loc The location for this caret. +/// \param Level The diagnostic level currently being emitted. +/// \param Ranges The underlined ranges for this code snippet. +/// \param Hints The FixIt hints active for this diagnostic. +/// \param MacroSkipEnd The depth to stop skipping macro expansions. +/// \param OnMacroInst The current depth of the macro expansion stack. +void DiagnosticRenderer::emitMacroExpansionsAndCarets( + SourceLocation Loc, + DiagnosticsEngine::Level Level, + SmallVectorImpl<CharSourceRange>& Ranges, + ArrayRef<FixItHint> Hints, + unsigned &MacroDepth, + unsigned OnMacroInst) +{ + assert(!Loc.isInvalid() && "must have a valid source location here"); + + // If this is a file source location, directly emit the source snippet and + // caret line. Also record the macro depth reached. + if (Loc.isFileID()) { + assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!"); + MacroDepth = OnMacroInst; + emitCodeContext(Loc, Level, Ranges, Hints); + return; + } + // Otherwise recurse through each macro expansion layer. + + // When processing macros, skip over the expansions leading up to + // a macro argument, and trace the argument's expansion stack instead. + Loc = skipToMacroArgExpansion(SM, Loc); + + SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc); + + // FIXME: Map ranges? + emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, MacroDepth, + OnMacroInst + 1); + + // Save the original location so we can find the spelling of the macro call. + SourceLocation MacroLoc = Loc; + + // Map the location. + Loc = getImmediateMacroCalleeLoc(SM, Loc); + + unsigned MacroSkipStart = 0, MacroSkipEnd = 0; + if (MacroDepth > DiagOpts.MacroBacktraceLimit) { + MacroSkipStart = DiagOpts.MacroBacktraceLimit / 2 + + DiagOpts.MacroBacktraceLimit % 2; + MacroSkipEnd = MacroDepth - DiagOpts.MacroBacktraceLimit / 2; + } + + // Whether to suppress printing this macro expansion. + bool Suppressed = (OnMacroInst >= MacroSkipStart && + OnMacroInst < MacroSkipEnd); + + // Map the ranges. + for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(), + E = Ranges.end(); + I != E; ++I) { + SourceLocation Start = I->getBegin(), End = I->getEnd(); + if (Start.isMacroID()) + I->setBegin(getImmediateMacroCalleeLoc(SM, Start)); + if (End.isMacroID()) + I->setEnd(getImmediateMacroCalleeLoc(SM, End)); + } + + if (Suppressed) { + // Tell the user that we've skipped contexts. + if (OnMacroInst == MacroSkipStart) { + llvm::SmallString<200> MessageStorage; + llvm::raw_svector_ostream Message(MessageStorage); + Message << "(skipping " << (MacroSkipEnd - MacroSkipStart) + << " expansions in backtrace; use -fmacro-backtrace-limit=0 to " + "see all)"; + emitBasicNote(Message.str()); + } + return; + } + + llvm::SmallString<100> MessageStorage; + llvm::raw_svector_ostream Message(MessageStorage); + Message << "expanded from macro '" + << getImmediateMacroName(MacroLoc, SM, LangOpts) << "'"; + emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note, + Message.str(), + Ranges, ArrayRef<FixItHint>()); +} + diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp index 425bc26fcc..d2b8660c62 100644 --- a/lib/Frontend/TextDiagnostic.cpp +++ b/lib/Frontend/TextDiagnostic.cpp @@ -174,70 +174,6 @@ static void selectInterestingSourceRegion(std::string &SourceLine, } } -/// Look through spelling locations for a macro argument expansion, and -/// if found skip to it so that we can trace the argument rather than the macros -/// in which that argument is used. If no macro argument expansion is found, -/// don't skip anything and return the starting location. -static SourceLocation skipToMacroArgExpansion(const SourceManager &SM, - SourceLocation StartLoc) { - for (SourceLocation L = StartLoc; L.isMacroID(); - L = SM.getImmediateSpellingLoc(L)) { - if (SM.isMacroArgExpansion(L)) - return L; - } - - // Otherwise just return initial location, there's nothing to skip. - return StartLoc; -} - -/// Gets the location of the immediate macro caller, one level up the stack -/// toward the initial macro typed into the source. -static SourceLocation getImmediateMacroCallerLoc(const SourceManager &SM, - SourceLocation Loc) { - if (!Loc.isMacroID()) return Loc; - - // When we have the location of (part of) an expanded parameter, its spelling - // location points to the argument as typed into the macro call, and - // therefore is used to locate the macro caller. - if (SM.isMacroArgExpansion(Loc)) - return SM.getImmediateSpellingLoc(Loc); - - // Otherwise, the caller of the macro is located where this macro is - // expanded (while the spelling is part of the macro definition). - return SM.getImmediateExpansionRange(Loc).first; -} - -/// Gets the location of the immediate macro callee, one level down the stack -/// toward the leaf macro. -static SourceLocation getImmediateMacroCalleeLoc(const SourceManager &SM, - SourceLocation Loc) { - if (!Loc.isMacroID()) return Loc; - - // When we have the location of (part of) an expanded parameter, its - // expansion location points to the unexpanded paramater reference within - // the macro definition (or callee). - if (SM.isMacroArgExpansion(Loc)) - return SM.getImmediateExpansionRange(Loc).first; - - // Otherwise, the callee of the macro is located where this location was - // spelled inside the macro definition. - return SM.getImmediateSpellingLoc(Loc); -} - -/// Get the presumed location of a diagnostic message. This computes the -/// presumed location for the top of any macro backtrace when present. -static PresumedLoc getDiagnosticPresumedLoc(const SourceManager &SM, - SourceLocation Loc) { - // This is a condensed form of the algorithm used by emitCaretDiagnostic to - // walk to the top of the macro call stack. - while (Loc.isMacroID()) { - Loc = skipToMacroArgExpansion(SM, Loc); - Loc = getImmediateMacroCallerLoc(SM, Loc); - } - - return SM.getPresumedLoc(Loc); -} - /// \brief Skip over whitespace in the string, starting at the given /// index. /// @@ -389,85 +325,33 @@ static bool printWordWrapped(raw_ostream &OS, StringRef Str, return Wrapped; } -/// \brief Retrieve the name of the immediate macro expansion. -/// -/// This routine starts from a source location, and finds the name of the macro -/// responsible for its immediate expansion. It looks through any intervening -/// macro argument expansions to compute this. It returns a StringRef which -/// refers to the SourceManager-owned buffer of the source where that macro -/// name is spelled. Thus, the result shouldn't out-live that SourceManager. -/// -static StringRef getImmediateMacroName(SourceLocation Loc, - const SourceManager &SM, - const LangOptions &LangOpts) { - assert(Loc.isMacroID() && "Only reasonble to call this on macros"); - // Walk past macro argument expanions. - while (SM.isMacroArgExpansion(Loc)) - Loc = SM.getImmediateExpansionRange(Loc).first; - - // Find the spelling location of the start of the non-argument expansion - // range. This is where the macro name was spelled in order to begin - // expanding this macro. - Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first); - - // Dig out the buffer where the macro name was spelled and the extents of the - // name so that we can render it into the expansion note. - std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc); - unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts); - StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first); - return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength); -} - TextDiagnostic::TextDiagnostic(raw_ostream &OS, const SourceManager &SM, const LangOptions &LangOpts, const DiagnosticOptions &DiagOpts) - : OS(OS), SM(SM), LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() { -} - -void TextDiagnostic::emitDiagnostic(SourceLocation Loc, - DiagnosticsEngine::Level Level, - StringRef Message, - ArrayRef<CharSourceRange> Ranges, - ArrayRef<FixItHint> FixItHints) { - PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, Loc); + : DiagnosticRenderer(SM, LangOpts, DiagOpts), OS(OS) {} - // First, if this diagnostic is not in the main file, print out the - // "included from" lines. - emitIncludeStack(PLoc.getIncludeLoc(), Level); +TextDiagnostic::~TextDiagnostic() {} +void +TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc, + PresumedLoc PLoc, + DiagnosticsEngine::Level Level, + StringRef Message, + ArrayRef<clang::CharSourceRange> Ranges, + const Diagnostic *Info) { uint64_t StartOfLocationInfo = OS.tell(); - // Next emit the location of this particular diagnostic. + // Emit the location of this particular diagnostic. emitDiagnosticLoc(Loc, PLoc, Level, Ranges); - + if (DiagOpts.ShowColors) OS.resetColor(); - + printDiagnosticLevel(OS, Level, DiagOpts.ShowColors); printDiagnosticMessage(OS, Level, Message, OS.tell() - StartOfLocationInfo, DiagOpts.MessageLength, DiagOpts.ShowColors); - - // Only recurse if we have a valid location. - if (Loc.isValid()) { - // Get the ranges into a local array we can hack on. - SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(), - Ranges.end()); - - for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(), - E = FixItHints.end(); - I != E; ++I) - if (I->RemoveRange.isValid()) - MutableRanges.push_back(I->RemoveRange); - - unsigned MacroDepth = 0; - emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints, - MacroDepth); - } - - LastLoc = Loc; - LastLevel = Level; } /*static*/ void @@ -525,50 +409,6 @@ TextDiagnostic::printDiagnosticMessage(raw_ostream &OS, OS << '\n'; } -/// \brief Prints an include stack when appropriate for a particular -/// diagnostic level and location. -/// -/// This routine handles all the logic of suppressing particular include -/// stacks (such as those for notes) and duplicate include stacks when -/// repeated warnings occur within the same file. It also handles the logic -/// of customizing the formatting and display of the include stack. -/// -/// \param Level The diagnostic level of the message this stack pertains to. -/// \param Loc The include location of the current file (not the diagnostic -/// location). -void TextDiagnostic::emitIncludeStack(SourceLocation Loc, - DiagnosticsEngine::Level Level) { - // Skip redundant include stacks altogether. - if (LastIncludeLoc == Loc) - return; - LastIncludeLoc = Loc; - - if (!DiagOpts.ShowNoteIncludeStack && Level == DiagnosticsEngine::Note) - return; - - emitIncludeStackRecursively(Loc); -} - -/// \brief Helper to recursivly walk up the include stack and print each layer -/// on the way back down. -void TextDiagnostic::emitIncludeStackRecursively(SourceLocation Loc) { - if (Loc.isInvalid()) - return; - - PresumedLoc PLoc = SM.getPresumedLoc(Loc); - if (PLoc.isInvalid()) - return; - - // Emit the other include frames first. - emitIncludeStackRecursively(PLoc.getIncludeLoc()); - - if (DiagOpts.ShowLocation) - OS << "In file included from " << PLoc.getFilename() - << ':' << PLoc.getLine() << ":\n"; - else - OS << "In included file:\n"; -} - /// \brief Print out the file/line/column information and include trace. /// /// This method handlen the emission of the diagnostic location information. @@ -676,95 +516,19 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, OS << ' '; } -/// \brief Recursively emit notes for each macro expansion and caret -/// diagnostics where appropriate. -/// -/// Walks up the macro expansion stack printing expansion notes, the code -/// snippet, caret, underlines and FixItHint display as appropriate at each -/// level. -/// -/// \param Loc The location for this caret. -/// \param Level The diagnostic level currently being emitted. -/// \param Ranges The underlined ranges for this code snippet. -/// \param Hints The FixIt hints active for this diagnostic. -/// \param MacroSkipEnd The depth to stop skipping macro expansions. -/// \param OnMacroInst The current depth of the macro expansion stack. -void TextDiagnostic::emitMacroExpansionsAndCarets( - SourceLocation Loc, - DiagnosticsEngine::Level Level, - SmallVectorImpl<CharSourceRange>& Ranges, - ArrayRef<FixItHint> Hints, - unsigned &MacroDepth, - unsigned OnMacroInst) { - assert(!Loc.isInvalid() && "must have a valid source location here"); - - // If this is a file source location, directly emit the source snippet and - // caret line. Also record the macro depth reached. - if (Loc.isFileID()) { - assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!"); - MacroDepth = OnMacroInst; - emitSnippetAndCaret(Loc, Level, Ranges, Hints); - return; - } - // Otherwise recurse through each macro expansion layer. - - // When processing macros, skip over the expansions leading up to - // a macro argument, and trace the argument's expansion stack instead. - Loc = skipToMacroArgExpansion(SM, Loc); - - SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc); - - // FIXME: Map ranges? - emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, MacroDepth, - OnMacroInst + 1); - - // Save the original location so we can find the spelling of the macro call. - SourceLocation MacroLoc = Loc; - - // Map the location. - Loc = getImmediateMacroCalleeLoc(SM, Loc); - - unsigned MacroSkipStart = 0, MacroSkipEnd = 0; - if (MacroDepth > DiagOpts.MacroBacktraceLimit) { - MacroSkipStart = DiagOpts.MacroBacktraceLimit / 2 + - DiagOpts.MacroBacktraceLimit % 2; - MacroSkipEnd = MacroDepth - DiagOpts.MacroBacktraceLimit / 2; - } - - // Whether to suppress printing this macro expansion. - bool Suppressed = (OnMacroInst >= MacroSkipStart && - OnMacroInst < MacroSkipEnd); - - // Map the ranges. - for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(), - E = Ranges.end(); - I != E; ++I) { - SourceLocation Start = I->getBegin(), End = I->getEnd(); - if (Start.isMacroID()) - I->setBegin(getImmediateMacroCalleeLoc(SM, Start)); - if (End.isMacroID()) - I->setEnd(getImmediateMacroCalleeLoc(SM, End)); - } - - if (Suppressed) { - // Tell the user that we've skipped contexts. - if (OnMacroInst == MacroSkipStart) { - // FIXME: Emit this as a real note diagnostic. - // FIXME: Format an actual diagnostic rather than a hard coded string. - OS << "note: (skipping " << (MacroSkipEnd - MacroSkipStart) - << " expansions in backtrace; use -fmacro-backtrace-limit=0 to see " - "all)\n"; - } - return; - } +void TextDiagnostic::emitBasicNote(StringRef Message) { + // FIXME: Emit this as a real note diagnostic. + // FIXME: Format an actual diagnostic rather than a hard coded string. + OS << "note: " << Message << "\n"; +} - llvm::SmallString<100> MessageStorage; - llvm::raw_svector_ostream Message(MessageStorage); - Message << "expanded from macro '" - << getImmediateMacroName(MacroLoc, SM, LangOpts) << "'"; - emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note, - Message.str(), - Ranges, ArrayRef<FixItHint>()); +void TextDiagnostic::emitIncludeLocation(SourceLocation Loc, + PresumedLoc PLoc) { + if (DiagOpts.ShowLocation) + OS << "In file included from " << PLoc.getFilename() << ':' + << PLoc.getLine() << ":\n"; + else + OS << "In included file:\n"; } /// \brief Emit a code snippet and caret line. |