forked from OSchip/llvm-project
Introduce a limit on the depth of the template instantiation backtrace
we will print with each error that occurs during template instantiation. When the backtrace is longer than that, we will print N/2 of the innermost backtrace entries and N/2 of the outermost backtrace entries, then skip the middle entries with a note such as: note: suppressed 2 template instantiation contexts; use -ftemplate-backtrace-limit=N to change the number of template instantiation entries shown This should eliminate some excessively long backtraces that aren't providing any value. llvm-svn: 101882
This commit is contained in:
parent
5debc33168
commit
ffed1cb339
|
@ -193,6 +193,8 @@ introduces the language selection and other high level options like -c, -g, etc.
|
|||
been produced. The default is 20, and the error limit can be disabled with
|
||||
-ferror-limit=0.</p>
|
||||
|
||||
<p><b>-ftemplate-backtrace-limit=123</b>: Only emit up to 123 template instantiation notes within the template instantiation backtrace for a single warning or error. The default is 10, and the limit can be disabled with -ftemplate-backtrace-limit=0.</p>
|
||||
|
||||
<!-- ================================================= -->
|
||||
<h4 id="cl_diag_formatting">Formatting of Diagnostics</h4>
|
||||
<!-- ================================================= -->
|
||||
|
|
|
@ -189,6 +189,8 @@ private:
|
|||
bool SuppressSystemWarnings; // Suppress warnings in system headers.
|
||||
bool SuppressAllDiagnostics; // Suppress all diagnostics.
|
||||
unsigned ErrorLimit; // Cap of # errors emitted, 0 -> no limit.
|
||||
unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
|
||||
// 0 -> no limit.
|
||||
ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
|
||||
DiagnosticClient *Client;
|
||||
|
||||
|
@ -276,6 +278,18 @@ public:
|
|||
/// emit before giving up. Zero disables the limit.
|
||||
void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; }
|
||||
|
||||
/// \brief Specify the maximum number of template instantiation
|
||||
/// notes to emit along with a given diagnostic.
|
||||
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; }
|
||||
|
|
|
@ -1434,7 +1434,10 @@ def note_prior_template_arg_substitution : Note<
|
|||
" template parameter%1 %2">;
|
||||
def note_template_default_arg_checking : Note<
|
||||
"while checking a default template argument used here">;
|
||||
|
||||
def note_instantiation_contexts_suppressed : Note<
|
||||
"suppressed %0 template instantiation context%s0; use -ftemplate-backtrace-"
|
||||
"limit=N to change the number of template instantiation entries shown">;
|
||||
|
||||
def err_field_instantiates_to_function : Error<
|
||||
"data member instantiated with function type %0">;
|
||||
def err_nested_name_spec_non_tag : Error<
|
||||
|
|
|
@ -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 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>">,
|
||||
HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
|
||||
def fcolor_diagnostics : Flag<"-fcolor-diagnostics">,
|
||||
|
|
|
@ -366,6 +366,8 @@ def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>;
|
|||
def ftabstop_EQ : Joined<"-ftabstop=">, Group<f_Group>;
|
||||
def ferror_limit_EQ : Joined<"-ferror-limit=">, Group<f_Group>;
|
||||
def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>;
|
||||
def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">,
|
||||
Group<f_Group>;
|
||||
def fterminated_vtables : Flag<"-fterminated-vtables">, Group<f_Group>;
|
||||
def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>;
|
||||
def ftime_report : Flag<"-ftime-report">, Group<f_Group>;
|
||||
|
|
|
@ -39,7 +39,8 @@ public:
|
|||
/// deserialized by, e.g., the CIndex library.
|
||||
|
||||
unsigned ErrorLimit; /// Limit # errors emitted.
|
||||
|
||||
unsigned TemplateBacktraceLimit; /// Limit depth of instantiation backtrace.
|
||||
|
||||
/// The distance between tab stops.
|
||||
unsigned TabStop;
|
||||
enum { DefaultTabStop = 8, MaxTabStop = 100 };
|
||||
|
@ -73,6 +74,7 @@ public:
|
|||
VerifyDiagnostics = 0;
|
||||
BinaryOutput = 0;
|
||||
ErrorLimit = 0;
|
||||
TemplateBacktraceLimit = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -224,7 +224,8 @@ Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
|
|||
ErrorOccurred = false;
|
||||
FatalErrorOccurred = false;
|
||||
ErrorLimit = 0;
|
||||
|
||||
TemplateBacktraceLimit = 0;
|
||||
|
||||
NumWarnings = 0;
|
||||
NumErrors = 0;
|
||||
NumErrorsSuppressed = 0;
|
||||
|
|
|
@ -1079,6 +1079,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
CmdArgs.push_back(A->getValue(Args));
|
||||
else
|
||||
CmdArgs.push_back("19");
|
||||
|
||||
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");
|
||||
|
||||
// Pass -fmessage-length=.
|
||||
CmdArgs.push_back("-fmessage-length");
|
||||
|
|
|
@ -240,6 +240,11 @@ static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts,
|
|||
Res.push_back("-ferror-limit");
|
||||
Res.push_back(llvm::utostr(Opts.ErrorLimit));
|
||||
}
|
||||
if (Opts.TemplateBacktraceLimit != 10) {
|
||||
Res.push_back("-ftemplate-backtrace-limit");
|
||||
Res.push_back(llvm::utostr(Opts.TemplateBacktraceLimit));
|
||||
}
|
||||
|
||||
if (Opts.TabStop != DiagnosticOptions::DefaultTabStop) {
|
||||
Res.push_back("-ftabstop");
|
||||
Res.push_back(llvm::utostr(Opts.TabStop));
|
||||
|
@ -857,6 +862,8 @@ 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.TemplateBacktraceLimit
|
||||
= getLastArgIntValue(Args, OPT_ftemplate_backtrace_limit, 0, Diags);
|
||||
Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop,
|
||||
DiagnosticOptions::DefaultTabStop, Diags);
|
||||
if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
|
||||
|
|
|
@ -39,6 +39,8 @@ void clang::ProcessWarningOptions(Diagnostic &Diags,
|
|||
// Handle -ferror-limit
|
||||
if (Opts.ErrorLimit)
|
||||
Diags.setErrorLimit(Opts.ErrorLimit);
|
||||
if (Opts.TemplateBacktraceLimit)
|
||||
Diags.setTemplateBacktraceLimit(Opts.TemplateBacktraceLimit);
|
||||
|
||||
// If -pedantic or -pedantic-errors was specified, then we want to map all
|
||||
// extension diagnostics onto WARNING or ERROR unless the user has futz'd
|
||||
|
|
|
@ -339,12 +339,32 @@ bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
|
|||
/// \brief Prints the current instantiation stack through a series of
|
||||
/// notes.
|
||||
void Sema::PrintInstantiationStack() {
|
||||
// Determine which template instantiations to skip, if any.
|
||||
unsigned SkipStart = ActiveTemplateInstantiations.size(), SkipEnd = SkipStart;
|
||||
unsigned Limit = Diags.getTemplateBacktraceLimit();
|
||||
if (Limit && Limit < ActiveTemplateInstantiations.size()) {
|
||||
SkipStart = Limit / 2 + Limit % 2;
|
||||
SkipEnd = ActiveTemplateInstantiations.size() - Limit / 2;
|
||||
}
|
||||
|
||||
// FIXME: In all of these cases, we need to show the template arguments
|
||||
unsigned InstantiationIdx = 0;
|
||||
for (llvm::SmallVector<ActiveTemplateInstantiation, 16>::reverse_iterator
|
||||
Active = ActiveTemplateInstantiations.rbegin(),
|
||||
ActiveEnd = ActiveTemplateInstantiations.rend();
|
||||
Active != ActiveEnd;
|
||||
++Active) {
|
||||
++Active, ++InstantiationIdx) {
|
||||
// Skip this instantiation?
|
||||
if (InstantiationIdx >= SkipStart && InstantiationIdx < SkipEnd) {
|
||||
if (InstantiationIdx == SkipStart) {
|
||||
// Note that we're skipping instantiations.
|
||||
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
||||
diag::note_instantiation_contexts_suppressed)
|
||||
<< unsigned(ActiveTemplateInstantiations.size() - Limit);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (Active->Kind) {
|
||||
case ActiveTemplateInstantiation::TemplateInstantiation: {
|
||||
Decl *D = reinterpret_cast<Decl *>(Active->Entity);
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -ftemplate-depth 5 -verify %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify -ftemplate-depth 5 -ftemplate-backtrace-limit 4 %s
|
||||
|
||||
template<typename T> struct X : X<T*> { }; // expected-error{{recursive template instantiation exceeded maximum depth of 5}} \
|
||||
// expected-note{{use -ftemplate-depth-N to increase recursive template instantiation depth}} \
|
||||
// expected-note 5 {{instantiation of template class}}
|
||||
template<typename T> struct X : X<T*> { }; \
|
||||
// expected-error{{recursive template instantiation exceeded maximum depth of 5}} \
|
||||
// expected-note 3 {{instantiation of template class}} \
|
||||
// expected-note {{suppressed 2 template instantiation contexts}} \
|
||||
// expected-note {{use -ftemplate-depth-N to increase recursive template instantiation depth}}
|
||||
|
||||
void test() {
|
||||
(void)sizeof(X<int>); // expected-note {{instantiation of template class}}
|
||||
|
|
Loading…
Reference in New Issue