1 //===--- 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> 20 using 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. 26 static 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. 40 static 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. 57 static 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 /// 80 /// This differs from Lexer::getImmediateMacroName in that any macro argument 81 /// location will result in the topmost function macro that accepted it. 82 /// e.g. 83 /// \code 84 /// MAC1( MAC2(foo) ) 85 /// \endcode 86 /// for location of 'foo' token, this function will return "MAC1" while 87 /// Lexer::getImmediateMacroName will return "MAC2". 88 static StringRef getImmediateMacroName(SourceLocation Loc, 89 const SourceManager &SM, 90 const LangOptions &LangOpts) { 91 assert(Loc.isMacroID() && "Only reasonble to call this on macros"); 92 // Walk past macro argument expanions. 93 while (SM.isMacroArgExpansion(Loc)) 94 Loc = SM.getImmediateExpansionRange(Loc).first; 95 96 // Find the spelling location of the start of the non-argument expansion 97 // range. This is where the macro name was spelled in order to begin 98 // expanding this macro. 99 Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first); 100 101 // Dig out the buffer where the macro name was spelled and the extents of the 102 // name so that we can render it into the expansion note. 103 std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc); 104 unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts); 105 StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first); 106 return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength); 107 } 108 109 /// Get the presumed location of a diagnostic message. This computes the 110 /// presumed location for the top of any macro backtrace when present. 111 static PresumedLoc getDiagnosticPresumedLoc(const SourceManager &SM, 112 SourceLocation Loc) { 113 // This is a condensed form of the algorithm used by emitCaretDiagnostic to 114 // walk to the top of the macro call stack. 115 while (Loc.isMacroID()) { 116 Loc = skipToMacroArgExpansion(SM, Loc); 117 Loc = getImmediateMacroCallerLoc(SM, Loc); 118 } 119 120 return SM.getPresumedLoc(Loc); 121 } 122 123 DiagnosticRenderer::DiagnosticRenderer(const SourceManager &SM, 124 const LangOptions &LangOpts, 125 const DiagnosticOptions &DiagOpts) 126 : SM(SM), LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {} 127 128 DiagnosticRenderer::~DiagnosticRenderer() {} 129 130 131 void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, 132 DiagnosticsEngine::Level Level, 133 StringRef Message, 134 ArrayRef<CharSourceRange> Ranges, 135 ArrayRef<FixItHint> FixItHints, 136 const Diagnostic *Info) { 137 138 beginDiagnostic(Info, Level); 139 140 PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, Loc); 141 142 // First, if this diagnostic is not in the main file, print out the 143 // "included from" lines. 144 emitIncludeStack(PLoc.getIncludeLoc(), Level); 145 146 // Next, emit the actual diagnostic message. 147 emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, Info); 148 149 // Only recurse if we have a valid location. 150 if (Loc.isValid()) { 151 // Get the ranges into a local array we can hack on. 152 SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(), 153 Ranges.end()); 154 155 for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(), 156 E = FixItHints.end(); 157 I != E; ++I) 158 if (I->RemoveRange.isValid()) 159 MutableRanges.push_back(I->RemoveRange); 160 161 unsigned MacroDepth = 0; 162 emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints, 163 MacroDepth); 164 } 165 166 LastLoc = Loc; 167 LastLevel = Level; 168 169 endDiagnostic(Info, Level); 170 } 171 172 /// \brief Prints an include stack when appropriate for a particular 173 /// diagnostic level and location. 174 /// 175 /// This routine handles all the logic of suppressing particular include 176 /// stacks (such as those for notes) and duplicate include stacks when 177 /// repeated warnings occur within the same file. It also handles the logic 178 /// of customizing the formatting and display of the include stack. 179 /// 180 /// \param Level The diagnostic level of the message this stack pertains to. 181 /// \param Loc The include location of the current file (not the diagnostic 182 /// location). 183 void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, 184 DiagnosticsEngine::Level Level) { 185 // Skip redundant include stacks altogether. 186 if (LastIncludeLoc == Loc) 187 return; 188 LastIncludeLoc = Loc; 189 190 if (!DiagOpts.ShowNoteIncludeStack && Level == DiagnosticsEngine::Note) 191 return; 192 193 emitIncludeStackRecursively(Loc); 194 } 195 196 /// \brief Helper to recursivly walk up the include stack and print each layer 197 /// on the way back down. 198 void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc) { 199 if (Loc.isInvalid()) 200 return; 201 202 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 203 if (PLoc.isInvalid()) 204 return; 205 206 // Emit the other include frames first. 207 emitIncludeStackRecursively(PLoc.getIncludeLoc()); 208 209 // Emit the inclusion text/note. 210 emitIncludeLocation(Loc, PLoc); 211 } 212 213 /// \brief Recursively emit notes for each macro expansion and caret 214 /// diagnostics where appropriate. 215 /// 216 /// Walks up the macro expansion stack printing expansion notes, the code 217 /// snippet, caret, underlines and FixItHint display as appropriate at each 218 /// level. 219 /// 220 /// \param Loc The location for this caret. 221 /// \param Level The diagnostic level currently being emitted. 222 /// \param Ranges The underlined ranges for this code snippet. 223 /// \param Hints The FixIt hints active for this diagnostic. 224 /// \param MacroSkipEnd The depth to stop skipping macro expansions. 225 /// \param OnMacroInst The current depth of the macro expansion stack. 226 void DiagnosticRenderer::emitMacroExpansionsAndCarets( 227 SourceLocation Loc, 228 DiagnosticsEngine::Level Level, 229 SmallVectorImpl<CharSourceRange>& Ranges, 230 ArrayRef<FixItHint> Hints, 231 unsigned &MacroDepth, 232 unsigned OnMacroInst) 233 { 234 assert(!Loc.isInvalid() && "must have a valid source location here"); 235 236 // If this is a file source location, directly emit the source snippet and 237 // caret line. Also record the macro depth reached. 238 if (Loc.isFileID()) { 239 assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!"); 240 MacroDepth = OnMacroInst; 241 emitCodeContext(Loc, Level, Ranges, Hints); 242 return; 243 } 244 // Otherwise recurse through each macro expansion layer. 245 246 // When processing macros, skip over the expansions leading up to 247 // a macro argument, and trace the argument's expansion stack instead. 248 Loc = skipToMacroArgExpansion(SM, Loc); 249 250 SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc); 251 252 // FIXME: Map ranges? 253 emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, MacroDepth, 254 OnMacroInst + 1); 255 256 // Save the original location so we can find the spelling of the macro call. 257 SourceLocation MacroLoc = Loc; 258 259 // Map the location. 260 Loc = getImmediateMacroCalleeLoc(SM, Loc); 261 262 unsigned MacroSkipStart = 0, MacroSkipEnd = 0; 263 if (MacroDepth > DiagOpts.MacroBacktraceLimit && 264 DiagOpts.MacroBacktraceLimit != 0) { 265 MacroSkipStart = DiagOpts.MacroBacktraceLimit / 2 + 266 DiagOpts.MacroBacktraceLimit % 2; 267 MacroSkipEnd = MacroDepth - DiagOpts.MacroBacktraceLimit / 2; 268 } 269 270 // Whether to suppress printing this macro expansion. 271 bool Suppressed = (OnMacroInst >= MacroSkipStart && 272 OnMacroInst < MacroSkipEnd); 273 274 // Map the ranges. 275 for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(), 276 E = Ranges.end(); 277 I != E; ++I) { 278 SourceLocation Start = I->getBegin(), End = I->getEnd(); 279 if (Start.isMacroID()) 280 I->setBegin(getImmediateMacroCalleeLoc(SM, Start)); 281 if (End.isMacroID()) 282 I->setEnd(getImmediateMacroCalleeLoc(SM, End)); 283 } 284 285 if (Suppressed) { 286 // Tell the user that we've skipped contexts. 287 if (OnMacroInst == MacroSkipStart) { 288 llvm::SmallString<200> MessageStorage; 289 llvm::raw_svector_ostream Message(MessageStorage); 290 Message << "(skipping " << (MacroSkipEnd - MacroSkipStart) 291 << " expansions in backtrace; use -fmacro-backtrace-limit=0 to " 292 "see all)"; 293 emitBasicNote(Message.str()); 294 } 295 return; 296 } 297 298 llvm::SmallString<100> MessageStorage; 299 llvm::raw_svector_ostream Message(MessageStorage); 300 Message << "expanded from macro '" 301 << getImmediateMacroName(MacroLoc, SM, LangOpts) << "'"; 302 emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note, 303 Message.str(), 304 Ranges, ArrayRef<FixItHint>()); 305 } 306 307