]> granicus.if.org Git - clang/commitdiff
Use an iterative method instead of recursion for printing macro backtraces.
authorRichard Trieu <rtrieu@google.com>
Tue, 28 Jul 2015 20:53:46 +0000 (20:53 +0000)
committerRichard Trieu <rtrieu@google.com>
Tue, 28 Jul 2015 20:53:46 +0000 (20:53 +0000)
Store the locations for a macro expansion in a vector, then iterate over them
instead of using recursion.  This simplifies the logic around the backtrace
limit and gives easier access to the source locations.  No functionality change.

Patch by Zhengkai Wu.

Differential Revision: http://reviews.llvm.org/D11542

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@243477 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Frontend/DiagnosticRenderer.h
lib/Frontend/DiagnosticRenderer.cpp

index 84a0f50823bcfaf1fa1ff688e1b98ad072428c1b..c372fdd0872fad4e43674f5780e1e017be155e64 100644 (file)
@@ -117,13 +117,15 @@ private:
   void emitCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
                  ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints,
                  const SourceManager &SM);
+  void emitSingleMacroExpansion(SourceLocation Loc,
+                                DiagnosticsEngine::Level Level,
+                                ArrayRef<CharSourceRange> Ranges,
+                                const SourceManager &SM);
   void emitMacroExpansions(SourceLocation Loc,
                            DiagnosticsEngine::Level Level,
                            ArrayRef<CharSourceRange> Ranges,
                            ArrayRef<FixItHint> Hints,
-                           const SourceManager &SM,
-                           unsigned &MacroDepth,
-                           unsigned OnMacroInst = 0);
+                           const SourceManager &SM);
 public:
   /// \brief Emit a diagnostic.
   ///
index c63e98dbe4f1a8fec22a9fa0117f96bc7851b830..fe62c2a50442741fbbea36143347081ba0100ee7 100644 (file)
@@ -169,9 +169,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
     // If this location is within a macro, walk from UnexpandedLoc up to Loc
     // and produce a macro backtrace.
     if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) {
-      unsigned MacroDepth = 0;
-      emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM,
-                          MacroDepth);
+      emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM);
     }
   }
 
@@ -394,6 +392,39 @@ void DiagnosticRenderer::emitCaret(SourceLocation Loc,
   emitCodeContext(Loc, Level, SpellingRanges, Hints, SM);
 }
 
+/// \brief A helper function for emitMacroExpansion to print the
+/// macro expansion message
+void DiagnosticRenderer::emitSingleMacroExpansion(
+    SourceLocation Loc,
+    DiagnosticsEngine::Level Level,
+    ArrayRef<CharSourceRange> Ranges,
+    const SourceManager &SM) {
+  // Find the spelling location for the macro definition. We must use the
+  // spelling location here to avoid emitting a macro backtrace for the note.
+  SourceLocation SpellingLoc = Loc;
+
+  // If this is the expansion of a macro argument, point the caret at the
+  // use of the argument in the definition of the macro, not the expansion.
+  if (SM.isMacroArgExpansion(Loc))
+    SpellingLoc = SM.getImmediateExpansionRange(Loc).first;
+  SpellingLoc = SM.getSpellingLoc(SpellingLoc);
+
+  // Map the ranges into the FileID of the diagnostic location.
+  SmallVector<CharSourceRange, 4> SpellingRanges;
+  mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
+
+  SmallString<100> MessageStorage;
+  llvm::raw_svector_ostream Message(MessageStorage);
+  StringRef MacroName = getImmediateMacroName(Loc, SM, LangOpts);
+  if (MacroName.empty())
+    Message << "expanded from here";
+  else
+    Message << "expanded from macro '" << MacroName << "'";
+
+  emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(),
+                 SpellingRanges, None, &SM);
+}
+
 /// \brief Recursively emit notes for each macro expansion and caret
 /// diagnostics where appropriate.
 ///
@@ -405,71 +436,49 @@ void DiagnosticRenderer::emitCaret(SourceLocation Loc,
 /// \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 OnMacroInst The current depth of the macro expansion stack.
 void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc,
                                              DiagnosticsEngine::Level Level,
                                              ArrayRef<CharSourceRange> Ranges,
                                              ArrayRef<FixItHint> Hints,
-                                             const SourceManager &SM,
-                                             unsigned &MacroDepth,
-                                             unsigned OnMacroInst) {
+                                             const SourceManager &SM) {
   assert(!Loc.isInvalid() && "must have a valid source location here");
 
-  // Walk up to the caller of this macro, and produce a backtrace down to there.
-  SourceLocation OneLevelUp = SM.getImmediateMacroCallerLoc(Loc);
-  if (OneLevelUp.isMacroID())
-    emitMacroExpansions(OneLevelUp, Level, Ranges, Hints, SM,
-                        MacroDepth, OnMacroInst + 1);
-  else
-    MacroDepth = OnMacroInst + 1;
-
-  unsigned MacroSkipStart = 0, MacroSkipEnd = 0;
-  if (MacroDepth > DiagOpts->MacroBacktraceLimit &&
-      DiagOpts->MacroBacktraceLimit != 0) {
-    MacroSkipStart = DiagOpts->MacroBacktraceLimit / 2 +
-    DiagOpts->MacroBacktraceLimit % 2;
-    MacroSkipEnd = MacroDepth - DiagOpts->MacroBacktraceLimit / 2;
+  // Produce a stack of macro backtraces.
+  SmallVector<SourceLocation, 8> LocationStack;
+  while (Loc.isMacroID()) {
+    LocationStack.push_back(Loc);
+    Loc = SM.getImmediateMacroCallerLoc(Loc);
+    assert(!Loc.isInvalid() && "must have a valid source location here");
   }
 
-  // Whether to suppress printing this macro expansion.
-  bool Suppressed = (OnMacroInst >= MacroSkipStart &&
-                     OnMacroInst < MacroSkipEnd);
-
-  if (Suppressed) {
-    // Tell the user that we've skipped contexts.
-    if (OnMacroInst == MacroSkipStart) {
-      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());      
-    }
+  unsigned MacroDepth = LocationStack.size();
+  unsigned MacroLimit = DiagOpts->MacroBacktraceLimit;
+  if (MacroDepth <= MacroLimit || MacroLimit == 0) {
+    for (auto I = LocationStack.rbegin(), E = LocationStack.rend();
+         I != E; ++I)
+      emitSingleMacroExpansion(*I, Level, Ranges, SM);
     return;
   }
 
-  // Find the spelling location for the macro definition. We must use the
-  // spelling location here to avoid emitting a macro bactrace for the note.
-  SourceLocation SpellingLoc = Loc;
-  // If this is the expansion of a macro argument, point the caret at the
-  // use of the argument in the definition of the macro, not the expansion.
-  if (SM.isMacroArgExpansion(Loc))
-    SpellingLoc = SM.getImmediateExpansionRange(Loc).first;
-  SpellingLoc = SM.getSpellingLoc(SpellingLoc);
+  unsigned MacroStartMessages = MacroLimit / 2;
+  unsigned MacroEndMessages = MacroLimit / 2 + MacroLimit % 2;
 
-  // Map the ranges into the FileID of the diagnostic location.
-  SmallVector<CharSourceRange, 4> SpellingRanges;
-  mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
+  for (auto I = LocationStack.rbegin(),
+            E = LocationStack.rbegin() + MacroStartMessages;
+       I != E; ++I)
+    emitSingleMacroExpansion(*I, Level, Ranges, SM);
 
-  SmallString<100> MessageStorage;
+  SmallString<200> MessageStorage;
   llvm::raw_svector_ostream Message(MessageStorage);
-  StringRef MacroName = getImmediateMacroName(Loc, SM, LangOpts);
-  if (MacroName.empty())
-    Message << "expanded from here";
-  else
-    Message << "expanded from macro '" << MacroName << "'";
-  emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(),
-                 SpellingRanges, None, &SM);
+  Message << "(skipping " << (MacroDepth - MacroLimit)
+          << " expansions in backtrace; use -fmacro-backtrace-limit=0 to "
+             "see all)";
+  emitBasicNote(Message.str());
+
+  for (auto I = LocationStack.rend() - MacroEndMessages,
+            E = LocationStack.rend();
+       I != E; ++I)
+    emitSingleMacroExpansion(*I, Level, Ranges, SM);
 }
 
 DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {}