Introduce a limit on the depth of the macro instantiation backtrace
printed in a diagnostic, similar to the limit we already have on the
depth of the template instantiation backtrace. The macro instantiation
backtrace is limited to 10 "instantiated from:" diagnostics; when it's
longer than that, we'll show the first half, then say how many were
suppressed, then show the second half. The limit can be changed with
-fmacro-instantiation-limit=N, and turned off with N=0.

This eliminates a lot of note spew with libraries making use of the
Boost.Preprocess library.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103014 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 28bb17a..66ed956 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -285,7 +285,10 @@
                                                 const SourceManager &SM,
                                                 const FixItHint *Hints,
                                                 unsigned NumHints,
-                                                unsigned Columns) {
+                                                unsigned Columns,  
+                                                unsigned OnMacroInst,
+                                                unsigned MacroSkipStart,
+                                                unsigned MacroSkipEnd) {
   assert(LangOpts && "Unexpected diagnostic outside source file processing");
   assert(!Loc.isInvalid() && "must have a valid source location here");
 
@@ -293,10 +296,16 @@
   // instantiated (recursively) then emit information about where the token was
   // spelled from.
   if (!Loc.isFileID()) {
+    // Whether to suppress printing this macro instantiation.
+    bool Suppressed 
+      = OnMacroInst >= MacroSkipStart && OnMacroInst < MacroSkipEnd;
+    
+
     SourceLocation OneLevelUp = SM.getImmediateInstantiationRange(Loc).first;
     // FIXME: Map ranges?
-    EmitCaretDiagnostic(OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns);
-
+    EmitCaretDiagnostic(OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns,
+                        OnMacroInst + 1, MacroSkipStart, MacroSkipEnd);
+    
     // Map the location.
     Loc = SM.getImmediateSpellingLoc(Loc);
 
@@ -308,26 +317,38 @@
       Ranges[i] = SourceRange(S, E);
     }
 
-    // Get the pretty name, according to #line directives etc.
-    PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+    if (!Suppressed) {
+      // Get the pretty name, according to #line directives etc.
+      PresumedLoc PLoc = SM.getPresumedLoc(Loc);
 
-    // If this diagnostic is not in the main file, print out the "included from"
-    // lines.
-    if (LastWarningLoc != PLoc.getIncludeLoc()) {
-      LastWarningLoc = PLoc.getIncludeLoc();
-      PrintIncludeStack(LastWarningLoc, SM);
+      // If this diagnostic is not in the main file, print out the
+      // "included from" lines.
+      if (LastWarningLoc != PLoc.getIncludeLoc()) {
+        LastWarningLoc = PLoc.getIncludeLoc();
+        PrintIncludeStack(LastWarningLoc, SM);
+      }
+
+      if (DiagOpts->ShowLocation) {
+        // Emit the file/line/column that this expansion came from.
+        OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':';
+        if (DiagOpts->ShowColumn)
+          OS << PLoc.getColumn() << ':';
+        OS << ' ';
+      }
+      OS << "note: instantiated from:\n";
+      
+      EmitCaretDiagnostic(Loc, Ranges, NumRanges, SM, Hints, NumHints, Columns,
+                          OnMacroInst + 1, MacroSkipStart, MacroSkipEnd);
+      return;
     }
-
-    if (DiagOpts->ShowLocation) {
-      // Emit the file/line/column that this expansion came from.
-      OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':';
-      if (DiagOpts->ShowColumn)
-        OS << PLoc.getColumn() << ':';
-      OS << ' ';
+    
+    if (OnMacroInst == MacroSkipStart) {
+      // Tell the user that we've skipped contexts.
+      OS << "note: (skipping " << (MacroSkipEnd - MacroSkipStart) 
+      << " contexts in backtrace; use -fmacro-backtrace-limit=0 to see "
+      "all)\n";
     }
-    OS << "note: instantiated from:\n";
-
-    EmitCaretDiagnostic(Loc, Ranges, NumRanges, SM, Hints, NumHints, Columns);
+    
     return;
   }
 
@@ -866,10 +887,29 @@
       }
     }
 
+    unsigned MacroInstSkipStart = 0, MacroInstSkipEnd = 0;
+    if (DiagOpts && DiagOpts->MacroBacktraceLimit && !LastLoc.isFileID()) {
+      // Compute the length of the macro-instantiation backtrace, so that we
+      // can establish which steps in the macro backtrace we'll skip.
+      SourceLocation Loc = LastLoc;
+      unsigned Depth = 0;
+      do {
+        ++Depth;
+        Loc = LastLoc.getManager().getImmediateInstantiationRange(Loc).first;
+      } while (!Loc.isFileID());
+      
+      if (Depth > DiagOpts->MacroBacktraceLimit) {
+        MacroInstSkipStart = DiagOpts->MacroBacktraceLimit / 2 + 
+                             DiagOpts->MacroBacktraceLimit % 2;
+        MacroInstSkipEnd = Depth - DiagOpts->MacroBacktraceLimit / 2;
+      }
+    }        
+    
     EmitCaretDiagnostic(LastLoc, Ranges, NumRanges, LastLoc.getManager(),
                         Info.getFixItHints(),
                         Info.getNumFixItHints(),
-                        DiagOpts->MessageLength);
+                        DiagOpts->MessageLength, 
+                        0, MacroInstSkipStart, MacroInstSkipEnd);
   }
 
   OS.flush();