]> granicus.if.org Git - clang/commitdiff
Introduce a limit on the depth of the macro instantiation backtrace
authorDouglas Gregor <dgregor@apple.com>
Tue, 4 May 2010 17:13:42 +0000 (17:13 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 4 May 2010 17:13:42 +0000 (17:13 +0000)
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

include/clang/Basic/Diagnostic.h
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Driver/CC1Options.td
include/clang/Driver/Options.td
include/clang/Frontend/DiagnosticOptions.h
include/clang/Frontend/TextDiagnosticPrinter.h
lib/Driver/Tools.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Frontend/TextDiagnosticPrinter.cpp
test/Misc/macro-backtrace-limit.c [new file with mode: 0644]

index bf94af6cb60da68eaf974fb09195c4b62192221f..38fb4285ffbfc053559c6d82f7793773898629f7 100644 (file)
@@ -283,13 +283,13 @@ public:
   void setTemplateBacktraceLimit(unsigned Limit) {
     TemplateBacktraceLimit = Limit;
   }
-
+  
   /// \brief Retrieve the maximum number of template instantiation
   /// nodes to emit along with a given diagnostic.
   unsigned getTemplateBacktraceLimit() const {
     return TemplateBacktraceLimit;
   }
-
+  
   /// setIgnoreAllWarnings - When set to true, any unmapped warnings are
   /// ignored.  If this and WarningsAsErrors are both set, then this one wins.
   void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }
index 93ab858065404b419b496b6ad8122d2d34bc5ef9..6b40820da81472fa161d7026871f3eed590d7c74 100644 (file)
@@ -1457,7 +1457,7 @@ def note_template_default_arg_checking : Note<
   "while checking a default template argument used here">;
 def note_instantiation_contexts_suppressed : Note<
   "(skipping %0 context%s0 in backtrace; use -ftemplate-backtrace-limit=0 to "
-  "see  all)">;
+  "see all)">;
 
 def err_field_instantiates_to_function : Error<
   "data member instantiated with function type %0">;
index 18b54ef5e07265873699fd356e3045006ce30684..0badeb9efa54961f81a904402c11a3acda85e692 100644 (file)
@@ -200,6 +200,8 @@ def ftabstop : Separate<"-ftabstop">, MetaVarName<"<N>">,
   HelpText<"Set the tab stop distance.">;
 def ferror_limit : Separate<"-ferror-limit">, MetaVarName<"<N>">,
   HelpText<"Set the maximum number of errors to emit before stopping (0 = no limit).">;
+def fmacro_backtrace_limit : Separate<"-fmacro-backtrace-limit">, MetaVarName<"<N>">,
+  HelpText<"Set the maximum number of entries to print in a macro instantiation backtrace (0 = no limit).">;
 def ftemplate_backtrace_limit : Separate<"-ftemplate-backtrace-limit">, MetaVarName<"<N>">,
   HelpText<"Set the maximum number of entries to print in a template instantiation backtrace (0 = no limit).">;
 def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"<N>">,
index 2127e5724f9798547488d79a2919ef0cad762553..f6e69e045444a2214be102fc07c9bac8e47dff2d 100644 (file)
@@ -280,6 +280,8 @@ def flat__namespace : Flag<"-flat_namespace">;
 def flax_vector_conversions : Flag<"-flax-vector-conversions">, Group<f_Group>;
 def flimited_precision_EQ : Joined<"-flimited-precision=">, Group<f_Group>;
 def flto : Flag<"-flto">, Group<f_Group>;
+def fmacro_backtrace_limit_EQ : Joined<"-fmacro-backtrace-limit=">, 
+                                Group<f_Group>;
 def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>;
 def fmerge_all_constants : Flag<"-fmerge-all-constants">, Group<f_Group>;
 def fmessage_length_EQ : Joined<"-fmessage-length=">, Group<f_Group>;
index 797cb34023db35edcfda0e4e7823ae723a04df7c..b4f147bde7b773bd592ccb4b599d9d74084cfb9d 100644 (file)
@@ -39,11 +39,15 @@ public:
                                  /// deserialized by, e.g., the CIndex library.
 
   unsigned ErrorLimit;           /// Limit # errors emitted.
+  unsigned MacroBacktraceLimit;  /// Limit depth of macro instantiation 
+                                 /// backtrace.
   unsigned TemplateBacktraceLimit; /// Limit depth of instantiation backtrace.
 
   /// The distance between tab stops.
   unsigned TabStop;
-  enum { DefaultTabStop = 8, MaxTabStop = 100 };
+  enum { DefaultTabStop = 8, MaxTabStop = 100, 
+         DefaultMacroBacktraceLimit = 6,
+         DefaultTemplateBacktraceLimit = 10 };
 
   /// Column limit for formatting message diagnostics, or 0 if unused.
   unsigned MessageLength;
@@ -75,6 +79,7 @@ public:
     BinaryOutput = 0;
     ErrorLimit = 0;
     TemplateBacktraceLimit = 0;
+    MacroBacktraceLimit = 0;
   }
 };
 
index 336713661a28a30f38e9ee893d726bf033658c1a..ec4392fe5d54c4fbe671424070c0b606f24aa347 100644 (file)
@@ -71,12 +71,15 @@ public:
                            const SourceManager &SM,
                            const FixItHint *Hints,
                            unsigned NumHints,
-                           unsigned Columns);
+                           unsigned Columns,  
+                           unsigned OnMacroInst,
+                           unsigned MacroSkipStart,
+                           unsigned MacroSkipEnd);
 
   virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
                                 const DiagnosticInfo &Info);
 };
 
-} // end namspace clang
+} // end namespace clang
 
 #endif
index 176d491bc0cead0cd9f8a7505fb729c6da1e8179..5a3916d19ea7a444afa9054f1ecc08aa164eab90 100644 (file)
@@ -21,6 +21,7 @@
 #include "clang/Driver/Options.h"
 #include "clang/Driver/ToolChain.h"
 #include "clang/Driver/Util.h"
+#include "clang/Frontend/DiagnosticOptions.h"
 
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -1082,11 +1083,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   else
     CmdArgs.push_back("19");
 
+  CmdArgs.push_back("-fmacro-backtrace-limit");
+  if (Arg *A = Args.getLastArg(options::OPT_fmacro_backtrace_limit_EQ))
+    CmdArgs.push_back(A->getValue(Args));
+  else
+    CmdArgs.push_back(Args.MakeArgString(
+                   llvm::Twine(DiagnosticOptions::DefaultMacroBacktraceLimit)));
+                      
   CmdArgs.push_back("-ftemplate-backtrace-limit");
   if (Arg *A = Args.getLastArg(options::OPT_ftemplate_backtrace_limit_EQ))
     CmdArgs.push_back(A->getValue(Args));
   else
-    CmdArgs.push_back("10");
+    CmdArgs.push_back(Args.MakeArgString(
+                llvm::Twine(DiagnosticOptions::DefaultTemplateBacktraceLimit)));
   
   // Pass -fmessage-length=.
   CmdArgs.push_back("-fmessage-length");
index 8ffdde2aa9b555fdb02bb69511a1c3d87922f277..729c1dcc15e1ffbae27f87b6efcf85495d8e5b95 100644 (file)
@@ -247,7 +247,13 @@ static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts,
     Res.push_back("-ferror-limit");
     Res.push_back(llvm::utostr(Opts.ErrorLimit));
   }
-  if (Opts.TemplateBacktraceLimit != 10) {
+  if (Opts.MacroBacktraceLimit
+                        != DiagnosticOptions::DefaultMacroBacktraceLimit) {
+    Res.push_back("-fmacro-backtrace-limit");
+    Res.push_back(llvm::utostr(Opts.MacroBacktraceLimit));
+  }
+  if (Opts.TemplateBacktraceLimit
+                        != DiagnosticOptions::DefaultTemplateBacktraceLimit) {
     Res.push_back("-ftemplate-backtrace-limit");
     Res.push_back(llvm::utostr(Opts.TemplateBacktraceLimit));
   }
@@ -877,8 +883,13 @@ static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
   Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
   Opts.BinaryOutput = Args.hasArg(OPT_fdiagnostics_binary);
   Opts.ErrorLimit = getLastArgIntValue(Args, OPT_ferror_limit, 0, Diags);
+  Opts.MacroBacktraceLimit
+    = getLastArgIntValue(Args, OPT_fmacro_backtrace_limit, 
+                         DiagnosticOptions::DefaultMacroBacktraceLimit, Diags);
   Opts.TemplateBacktraceLimit
-    = getLastArgIntValue(Args, OPT_ftemplate_backtrace_limit, 0, Diags);
+    = getLastArgIntValue(Args, OPT_ftemplate_backtrace_limit, 
+                         DiagnosticOptions::DefaultTemplateBacktraceLimit, 
+                         Diags);
   Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop,
                                     DiagnosticOptions::DefaultTabStop, Diags);
   if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
index 28bb17ac3efa9ab1c196bf300ce7af04d39c91b3..66ed956a22a70491160454d1beaca03652867009 100644 (file)
@@ -285,7 +285,10 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
                                                 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 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
   // 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 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
       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 << ' ';
+      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;
     }
-    OS << "note: instantiated from:\n";
-
-    EmitCaretDiagnostic(Loc, Ranges, NumRanges, SM, Hints, NumHints, Columns);
+    
+    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";
+    }
+    
     return;
   }
 
@@ -866,10 +887,29 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
       }
     }
 
+    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();
diff --git a/test/Misc/macro-backtrace-limit.c b/test/Misc/macro-backtrace-limit.c
new file mode 100644 (file)
index 0000000..bc7a4da
--- /dev/null
@@ -0,0 +1,32 @@
+// RUN: %clang-cc1 -fsyntax-only -fmacro-backtrace-limit 5 %s > %t 2>&1 
+// RUN: FileCheck %s < %t
+
+#define M1(A, B) ((A) < (B))
+#define M2(A, B) M1(A, B)
+#define M3(A, B) M2(A, B)
+#define M4(A, B) M3(A, B)
+#define M5(A, B) M4(A, B)
+#define M6(A, B) M5(A, B)
+#define M7(A, B) M6(A, B)
+#define M8(A, B) M7(A, B)
+#define M9(A, B) M8(A, B)
+#define M10(A, B) M9(A, B)
+#define M11(A, B) M10(A, B)
+#define M12(A, B) M11(A, B)
+
+void f(int *ip, float *fp) {
+  // CHECK: macro-backtrace-limit.c:31:7: warning: comparison of distinct pointer types ('int *' and 'float *')
+  // CHECK: if (M12(ip, fp)) { }
+  // CHECK: macro-backtrace-limit.c:15:19: note: instantiated from:
+  // CHECK: #define M12(A, B) M11(A, B)
+  // CHECK: macro-backtrace-limit.c:14:19: note: instantiated from:
+  // CHECK: #define M11(A, B) M10(A, B)
+  // CHECK: note: (skipping 7 contexts in backtrace; use -fmacro-backtrace-limit=0 to see all)
+  // CHECK: macro-backtrace-limit.c:6:18: note: instantiated from:
+  // CHECK: #define M3(A, B) M2(A, B)
+  // CHECK: macro-backtrace-limit.c:5:18: note: instantiated from:
+  // CHECK: #define M2(A, B) M1(A, B)
+  // CHECK: macro-backtrace-limit.c:4:23: note: instantiated from:
+  // CHECK: #define M1(A, B) ((A) < (B))
+  if (M12(ip, fp)) { }
+}