diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-01-23 16:58:33 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-01-23 16:58:33 +0000 |
commit | 7f6cf9764b33381e03fcf7c44f7985a333212b06 (patch) | |
tree | 68d66b1860a5b4e471e3d320fa1a28d67310d4c6 /lib/Frontend/DiagnosticRenderer.cpp | |
parent | f5cd27d7eef3fd4021545dd76a1faf7152fda344 (diff) |
Improve Lexer::getImmediateMacroName to take into account inner macros
of macro arguments.
For "MAC1( MAC2(foo) )" and location of 'foo' token it would return
"MAC1" instead of "MAC2".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148704 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend/DiagnosticRenderer.cpp')
-rw-r--r-- | lib/Frontend/DiagnosticRenderer.cpp | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp index 913aa82d51..9c4976c210 100644 --- a/lib/Frontend/DiagnosticRenderer.cpp +++ b/lib/Frontend/DiagnosticRenderer.cpp @@ -69,6 +69,43 @@ static SourceLocation getImmediateMacroCalleeLoc(const SourceManager &SM, 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. +/// +/// This differs from Lexer::getImmediateMacroName in that any macro argument +/// location will result in the topmost function macro that accepted it. +/// e.g. +/// \code +/// MAC1( MAC2(foo) ) +/// \endcode +/// for location of 'foo' token, this function will return "MAC1" while +/// Lexer::getImmediateMacroName will return "MAC2". +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, @@ -260,7 +297,7 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets( llvm::SmallString<100> MessageStorage; llvm::raw_svector_ostream Message(MessageStorage); Message << "expanded from macro '" - << Lexer::getImmediateMacroName(MacroLoc, SM, LangOpts) << "'"; + << getImmediateMacroName(MacroLoc, SM, LangOpts) << "'"; emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note, Message.str(), Ranges, ArrayRef<FixItHint>()); |