blob: 293ffb7a4ed9414d3858a9b848a27d4a71836810 [file] [log] [blame]
Ted Kremenek2898d4f2011-12-17 05:26:04 +00001//===--- 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
10#include "clang/Frontend/DiagnosticRenderer.h"
11#include "clang/Basic/FileManager.h"
12#include "clang/Basic/SourceManager.h"
13#include "clang/Frontend/DiagnosticOptions.h"
14#include "clang/Lex/Lexer.h"
15#include "llvm/Support/MemoryBuffer.h"
16#include "llvm/Support/raw_ostream.h"
17#include "llvm/Support/ErrorHandling.h"
18#include "llvm/ADT/SmallString.h"
19#include <algorithm>
20using namespace clang;
21
22/// Look through spelling locations for a macro argument expansion, and
23/// if found skip to it so that we can trace the argument rather than the macros
24/// in which that argument is used. If no macro argument expansion is found,
25/// don't skip anything and return the starting location.
26static SourceLocation skipToMacroArgExpansion(const SourceManager &SM,
27 SourceLocation StartLoc) {
28 for (SourceLocation L = StartLoc; L.isMacroID();
29 L = SM.getImmediateSpellingLoc(L)) {
30 if (SM.isMacroArgExpansion(L))
31 return L;
32 }
33
34 // Otherwise just return initial location, there's nothing to skip.
35 return StartLoc;
36}
37
38/// Gets the location of the immediate macro caller, one level up the stack
39/// toward the initial macro typed into the source.
40static SourceLocation getImmediateMacroCallerLoc(const SourceManager &SM,
41 SourceLocation Loc) {
42 if (!Loc.isMacroID()) return Loc;
43
44 // When we have the location of (part of) an expanded parameter, its spelling
45 // location points to the argument as typed into the macro call, and
46 // therefore is used to locate the macro caller.
47 if (SM.isMacroArgExpansion(Loc))
48 return SM.getImmediateSpellingLoc(Loc);
49
50 // Otherwise, the caller of the macro is located where this macro is
51 // expanded (while the spelling is part of the macro definition).
52 return SM.getImmediateExpansionRange(Loc).first;
53}
54
55/// Gets the location of the immediate macro callee, one level down the stack
56/// toward the leaf macro.
57static SourceLocation getImmediateMacroCalleeLoc(const SourceManager &SM,
58 SourceLocation Loc) {
59 if (!Loc.isMacroID()) return Loc;
60
61 // When we have the location of (part of) an expanded parameter, its
62 // expansion location points to the unexpanded paramater reference within
63 // the macro definition (or callee).
64 if (SM.isMacroArgExpansion(Loc))
65 return SM.getImmediateExpansionRange(Loc).first;
66
67 // Otherwise, the callee of the macro is located where this location was
68 // spelled inside the macro definition.
69 return SM.getImmediateSpellingLoc(Loc);
70}
71
72/// \brief Retrieve the name of the immediate macro expansion.
73///
74/// This routine starts from a source location, and finds the name of the macro
75/// responsible for its immediate expansion. It looks through any intervening
76/// macro argument expansions to compute this. It returns a StringRef which
77/// refers to the SourceManager-owned buffer of the source where that macro
78/// name is spelled. Thus, the result shouldn't out-live that SourceManager.
79///
80static StringRef getImmediateMacroName(SourceLocation Loc,
81 const SourceManager &SM,
82 const LangOptions &LangOpts) {
83 assert(Loc.isMacroID() && "Only reasonble to call this on macros");
84 // Walk past macro argument expanions.
85 while (SM.isMacroArgExpansion(Loc))
86 Loc = SM.getImmediateExpansionRange(Loc).first;
87
88 // Find the spelling location of the start of the non-argument expansion
89 // range. This is where the macro name was spelled in order to begin
90 // expanding this macro.
91 Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first);
92
93 // Dig out the buffer where the macro name was spelled and the extents of the
94 // name so that we can render it into the expansion note.
95 std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc);
96 unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts);
97 StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first);
98 return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength);
99}
100
101/// Get the presumed location of a diagnostic message. This computes the
102/// presumed location for the top of any macro backtrace when present.
103static PresumedLoc getDiagnosticPresumedLoc(const SourceManager &SM,
104 SourceLocation Loc) {
105 // This is a condensed form of the algorithm used by emitCaretDiagnostic to
106 // walk to the top of the macro call stack.
107 while (Loc.isMacroID()) {
108 Loc = skipToMacroArgExpansion(SM, Loc);
109 Loc = getImmediateMacroCallerLoc(SM, Loc);
110 }
111
112 return SM.getPresumedLoc(Loc);
113}
114
115DiagnosticRenderer::DiagnosticRenderer(const SourceManager &SM,
116 const LangOptions &LangOpts,
117 const DiagnosticOptions &DiagOpts)
118: SM(SM), LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
119
120DiagnosticRenderer::~DiagnosticRenderer() {}
121
122
123void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
124 DiagnosticsEngine::Level Level,
125 StringRef Message,
126 ArrayRef<CharSourceRange> Ranges,
127 ArrayRef<FixItHint> FixItHints,
128 const Diagnostic *Info) {
129
130 beginDiagnostic(Info, Level);
131
132 PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, Loc);
133
134 // First, if this diagnostic is not in the main file, print out the
135 // "included from" lines.
136 emitIncludeStack(PLoc.getIncludeLoc(), Level);
137
138 // Next, emit the actual diagnostic message.
139 emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, Info);
140
141 // Only recurse if we have a valid location.
142 if (Loc.isValid()) {
143 // Get the ranges into a local array we can hack on.
144 SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(),
145 Ranges.end());
146
147 for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(),
148 E = FixItHints.end();
149 I != E; ++I)
150 if (I->RemoveRange.isValid())
151 MutableRanges.push_back(I->RemoveRange);
152
153 unsigned MacroDepth = 0;
154 emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints,
155 MacroDepth);
156 }
157
158 LastLoc = Loc;
159 LastLevel = Level;
160
161 endDiagnostic(Info, Level);
162}
163
164/// \brief Prints an include stack when appropriate for a particular
165/// diagnostic level and location.
166///
167/// This routine handles all the logic of suppressing particular include
168/// stacks (such as those for notes) and duplicate include stacks when
169/// repeated warnings occur within the same file. It also handles the logic
170/// of customizing the formatting and display of the include stack.
171///
172/// \param Level The diagnostic level of the message this stack pertains to.
173/// \param Loc The include location of the current file (not the diagnostic
174/// location).
175void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
176 DiagnosticsEngine::Level Level) {
177 // Skip redundant include stacks altogether.
178 if (LastIncludeLoc == Loc)
179 return;
180 LastIncludeLoc = Loc;
181
182 if (!DiagOpts.ShowNoteIncludeStack && Level == DiagnosticsEngine::Note)
183 return;
184
185 emitIncludeStackRecursively(Loc);
186}
187
188/// \brief Helper to recursivly walk up the include stack and print each layer
189/// on the way back down.
190void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc) {
191 if (Loc.isInvalid())
192 return;
193
194 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
195 if (PLoc.isInvalid())
196 return;
197
198 // Emit the other include frames first.
199 emitIncludeStackRecursively(PLoc.getIncludeLoc());
200
201 // Emit the inclusion text/note.
202 emitIncludeLocation(Loc, PLoc);
203}
204
205/// \brief Recursively emit notes for each macro expansion and caret
206/// diagnostics where appropriate.
207///
208/// Walks up the macro expansion stack printing expansion notes, the code
209/// snippet, caret, underlines and FixItHint display as appropriate at each
210/// level.
211///
212/// \param Loc The location for this caret.
213/// \param Level The diagnostic level currently being emitted.
214/// \param Ranges The underlined ranges for this code snippet.
215/// \param Hints The FixIt hints active for this diagnostic.
216/// \param MacroSkipEnd The depth to stop skipping macro expansions.
217/// \param OnMacroInst The current depth of the macro expansion stack.
218void DiagnosticRenderer::emitMacroExpansionsAndCarets(
219 SourceLocation Loc,
220 DiagnosticsEngine::Level Level,
221 SmallVectorImpl<CharSourceRange>& Ranges,
222 ArrayRef<FixItHint> Hints,
223 unsigned &MacroDepth,
224 unsigned OnMacroInst)
225{
226 assert(!Loc.isInvalid() && "must have a valid source location here");
227
228 // If this is a file source location, directly emit the source snippet and
229 // caret line. Also record the macro depth reached.
230 if (Loc.isFileID()) {
231 assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!");
232 MacroDepth = OnMacroInst;
233 emitCodeContext(Loc, Level, Ranges, Hints);
234 return;
235 }
236 // Otherwise recurse through each macro expansion layer.
237
238 // When processing macros, skip over the expansions leading up to
239 // a macro argument, and trace the argument's expansion stack instead.
240 Loc = skipToMacroArgExpansion(SM, Loc);
241
242 SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc);
243
244 // FIXME: Map ranges?
245 emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, MacroDepth,
246 OnMacroInst + 1);
247
248 // Save the original location so we can find the spelling of the macro call.
249 SourceLocation MacroLoc = Loc;
250
251 // Map the location.
252 Loc = getImmediateMacroCalleeLoc(SM, Loc);
253
254 unsigned MacroSkipStart = 0, MacroSkipEnd = 0;
255 if (MacroDepth > DiagOpts.MacroBacktraceLimit) {
256 MacroSkipStart = DiagOpts.MacroBacktraceLimit / 2 +
257 DiagOpts.MacroBacktraceLimit % 2;
258 MacroSkipEnd = MacroDepth - DiagOpts.MacroBacktraceLimit / 2;
259 }
260
261 // Whether to suppress printing this macro expansion.
262 bool Suppressed = (OnMacroInst >= MacroSkipStart &&
263 OnMacroInst < MacroSkipEnd);
264
265 // Map the ranges.
266 for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
267 E = Ranges.end();
268 I != E; ++I) {
269 SourceLocation Start = I->getBegin(), End = I->getEnd();
270 if (Start.isMacroID())
271 I->setBegin(getImmediateMacroCalleeLoc(SM, Start));
272 if (End.isMacroID())
273 I->setEnd(getImmediateMacroCalleeLoc(SM, End));
274 }
275
276 if (Suppressed) {
277 // Tell the user that we've skipped contexts.
278 if (OnMacroInst == MacroSkipStart) {
279 llvm::SmallString<200> MessageStorage;
280 llvm::raw_svector_ostream Message(MessageStorage);
281 Message << "(skipping " << (MacroSkipEnd - MacroSkipStart)
282 << " expansions in backtrace; use -fmacro-backtrace-limit=0 to "
283 "see all)";
284 emitBasicNote(Message.str());
285 }
286 return;
287 }
288
289 llvm::SmallString<100> MessageStorage;
290 llvm::raw_svector_ostream Message(MessageStorage);
291 Message << "expanded from macro '"
292 << getImmediateMacroName(MacroLoc, SM, LangOpts) << "'";
293 emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note,
294 Message.str(),
295 Ranges, ArrayRef<FixItHint>());
296}
297