summaryrefslogtreecommitdiffstats
path: root/lib/Frontend/TextDiagnostic.cpp
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2011-10-16 09:30:08 +0000
committerChandler Carruth <chandlerc@gmail.com>2011-10-16 09:30:08 +0000
commita47129e97be2379961046fac4f94f12ac15cb540 (patch)
tree0124269a49e79068a3cb3d800c5531bc7c8263a5 /lib/Frontend/TextDiagnostic.cpp
parent938ef249e9e5b5e3b7065c7f92b2578aa2dd971b (diff)
Now that macro expansion notes are real notes and go through the same
formatting as any other diagnostic, they will be properly line wrapped and otherwise pretty printed. Let's take advantage of that and the new factoring to add some helpful information to them (much like template backtrace notes and other notes): the name of the macro whose expansion is being noted. This makes a world of difference if caret diagnostics are disabled, making the expansion notes actually useful in this case. It also helps ensure that in edge cases the information the user needs is present. Consider: % nl -ba t5.cc 1 #define M(x, y, z) \ 2 y 3 4 M( 5 1, 6 2, 7 3); We now produce: % ./bin/clang -fsyntax-only t5.cc t5.cc:6:3: error: expected unqualified-id 2, ^ t5.cc:2:3: note: expanded from macro: M y ^ 1 error generated. Without the added information in the note, the name of the macro being expanded would never be shown. This also deletes a FIXME to use the diagnostic formatting. It's not yet clear to me that we *can* do this reasonably, and the production of this message was my primary goal here anyways. I'd love any comments or suggestions on improving these notes, their wording, etc. Currently, I need to make them provide more helpful information in the presence of a token-pasting buffer, and I'm pondering adding something along the lines of "expanded from argument N of macro: ...". git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142127 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend/TextDiagnostic.cpp')
-rw-r--r--lib/Frontend/TextDiagnostic.cpp25
1 files changed, 23 insertions, 2 deletions
diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp
index 7b3ebc4cd6..8dab0afcac 100644
--- a/lib/Frontend/TextDiagnostic.cpp
+++ b/lib/Frontend/TextDiagnostic.cpp
@@ -689,6 +689,9 @@ void TextDiagnostic::emitMacroExpansionsAndCarets(
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);
@@ -726,9 +729,27 @@ void TextDiagnostic::emitMacroExpansionsAndCarets(
return;
}
- // FIXME: Format an actual diagnostic rather than a hard coded string.
+ // Walk past macro argument expanions.
+ while (SM.isMacroArgExpansion(MacroLoc))
+ MacroLoc = SM.getImmediateExpansionRange(MacroLoc).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.
+ MacroLoc = SM.getSpellingLoc(SM.getImmediateExpansionRange(MacroLoc).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(MacroLoc);
+ unsigned MacroTokenLength = Lexer::MeasureTokenLength(MacroLoc, SM, LangOpts);
+ StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first);
+
+ llvm::SmallString<100> MessageStorage;
+ llvm::raw_svector_ostream Message(MessageStorage);
+ Message << "expanded from macro: "
+ << ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength);
emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note,
- "expanded from:",
+ Message.str(),
Ranges, ArrayRef<FixItHint>());
}