On Tue, 2024-08-06 at 17:52 -0400, Jason Merrill wrote: > On 8/6/24 5:47 PM, Patrick Palka wrote: > > On Tue, 6 Aug 2024, Jason Merrill wrote: > > > > > On 8/6/24 2:00 PM, Patrick Palka wrote: > > > > On Tue, 6 Aug 2024, Jason Merrill wrote: > > > > > > > > > On 8/5/24 6:09 PM, Patrick Palka wrote: > > > > > > On Mon, 5 Aug 2024, Jason Merrill wrote: > > > > > > > > > > > > > On 8/5/24 3:47 PM, Patrick Palka wrote: > > > > > > > > On Mon, 5 Aug 2024, Jason Merrill wrote: > > > > > > > > > > > > > > > > > On 8/5/24 1:14 PM, Patrick Palka wrote: > > > > > > > > > > On Mon, 5 Aug 2024, Jason Merrill wrote: > > > > > > > > > > > > > > > > > > > > > On 8/2/24 4:18 PM, Patrick Palka wrote: > > > > > > > > > > > > On Fri, 2 Aug 2024, Patrick Palka wrote: > > > > > > > > > > > > > > > > > > > > > > > > > On Fri, 2 Aug 2024, Jason Merrill wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > On 8/1/24 2:52 PM, Patrick Palka wrote: > > > > > > > > > > > > > > > In recent versions of GCC we've been > > > > > > > > > > > > > > > diagnosing more > > > > > > > > > > > > > > > and > > > > > > > > > > > > > > > more > > > > > > > > > > > > > > > kinds of > > > > > > > > > > > > > > > errors inside a template ahead of time. > > > > > > > > > > > > > > > This is a > > > > > > > > > > > > > > > largely > > > > > > > > > > > > > > > good > > > > > > > > > > > > > > > thing > > > > > > > > > > > > > > > because it catches bugs, typos, dead code > > > > > > > > > > > > > > > etc sooner. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > But if the template never gets > > > > > > > > > > > > > > > instantiated then such > > > > > > > > > > > > > > > errors > > > > > > > > > > > > > > > are > > > > > > > > > > > > > > > harmless, and can be inconvenient to work > > > > > > > > > > > > > > > around if > > > > > > > > > > > > > > > say > > > > > > > > > > > > > > > the > > > > > > > > > > > > > > > code > > > > > > > > > > > > > > > in > > > > > > > > > > > > > > > question is third party and in > > > > > > > > > > > > > > > maintenence mode. So > > > > > > > > > > > > > > > it'd > > > > > > > > > > > > > > > be > > > > > > > > > > > > > > > useful to > > > > > > > > > > > > > > > > > > > > > > > > > > > > "maintenance" > > > > > > > > > > > > > > > > > > > > > > > > > > Fixed > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > diff --git a/gcc/cp/error.cc > > > > > > > > > > > > > > > b/gcc/cp/error.cc > > > > > > > > > > > > > > > index d80bac822ba..0bb0a482e28 100644 > > > > > > > > > > > > > > > --- a/gcc/cp/error.cc > > > > > > > > > > > > > > > +++ b/gcc/cp/error.cc > > > > > > > > > > > > > > > @@ -165,6 +165,58 @@ class > > > > > > > > > > > > > > > cxx_format_postprocessor : > > > > > > > > > > > > > > > public > > > > > > > > > > > > > > > format_postprocessor > > > > > > > > > > > > > > > deferred_printed_type m_type_b; > > > > > > > > > > > > > > > }; > > > > > > > > > > > > > > > +/* A map from TEMPLATE_DECL to > > > > > > > > > > > > > > > the location of > > > > > > > > > > > > > > > the > > > > > > > > > > > > > > > first > > > > > > > > > > > > > > > error (if > > > > > > > > > > > > > > > any) > > > > > > > > > > > > > > > + within the template that we > > > > > > > > > > > > > > > permissivly downgraded > > > > > > > > > > > > > > > to > > > > > > > > > > > > > > > a > > > > > > > > > > > > > > > warning. > > > > > > > > > > > > > > > */ > > > > > > > > > > > > > > > > > > > > > > > > > > > > "permissively" > > > > > > > > > > > > > > > > > > > > > > > > > > Fixed > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > +relaxed_template_errors_t > > > > > > > > > > > > > > > *relaxed_template_errors; > > > > > > > > > > > > > > > + > > > > > > > > > > > > > > > +/* Callback function > > > > > > > > > > > > > > > diagnostic_context::m_adjust_diagnostic_i > > > > > > > > > > > > > > > nfo. > > > > > > > > > > > > > > > + > > > > > > > > > > > > > > > + In -fpermissive mode we downgrade > > > > > > > > > > > > > > > errors within a > > > > > > > > > > > > > > > template > > > > > > > > > > > > > > > to > > > > > > > > > > > > > > > + warnings, and only issue an error if > > > > > > > > > > > > > > > we later need > > > > > > > > > > > > > > > to > > > > > > > > > > > > > > > instantiate > > > > > > > > > > > > > > > + the template. */ > > > > > > > > > > > > > > > + > > > > > > > > > > > > > > > +static void > > > > > > > > > > > > > > > +cp_adjust_diagnostic_info > > > > > > > > > > > > > > > (diagnostic_context > > > > > > > > > > > > > > > *context, > > > > > > > > > > > > > > > + > > > > > > > > > > > > > > > diagnostic_info > > > > > > > > > > > > > > > *diagnostic) > > > > > > > > > > > > > > > +{ > > > > > > > > > > > > > > > + tree ti; > > > > > > > > > > > > > > > + if (diagnostic->kind == DK_ERROR > > > > > > > > > > > > > > > + && context->m_permissive > > > > > > > > > > > > > > > + && !current_instantiation () > > > > > > > > > > > > > > > + && in_template_context > > > > > > > > > > > > > > > + && (ti = get_template_info > > > > > > > > > > > > > > > (current_scope ()))) > > > > > > > > > > > > > > > + { > > > > > > > > > > > > > > > + if (!relaxed_template_errors) > > > > > > > > > > > > > > > + relaxed_template_errors = new > > > > > > > > > > > > > > > relaxed_template_errors_t; > > > > > > > > > > > > > > > + > > > > > > > > > > > > > > > + tree tmpl = TI_TEMPLATE (ti); > > > > > > > > > > > > > > > + if (!relaxed_template_errors->get > > > > > > > > > > > > > > > (tmpl)) > > > > > > > > > > > > > > > + relaxed_template_errors->put > > > > > > > > > > > > > > > (tmpl, > > > > > > > > > > > > > > > diagnostic->richloc->get_loc ()); > > > > > > > > > > > > > > > + diagnostic->kind = DK_WARNING; > > > > > > > > > > > > > > > > > > > > > > > > > > > > Rather than check m_permissive directly and > > > > > > > > > > > > > > downgrade to > > > > > > > > > > > > > > DK_WARNING, > > > > > > > > > > > > > > how > > > > > > > > > > > > > > about > > > > > > > > > > > > > > downgrading to DK_PERMERROR? That way > > > > > > > > > > > > > > people will get > > > > > > > > > > > > > > the > > > > > > > > > > > > > > [-fpermissive] > > > > > > > > > > > > > > clue. > > > > > > > > > > > > > > > > > > > > > > > > > > > > ...though I suppose DK_PERMERROR doesn't > > > > > > > > > > > > > > work where you > > > > > > > > > > > > > > call > > > > > > > > > > > > > > this > > > > > > > > > > > > > > hook > > > > > > > > > > > > > > in > > > > > > > > > > > > > > report_diagnostic, at which point we've > > > > > > > > > > > > > > already > > > > > > > > > > > > > > reassigned > > > > > > > > > > > > > > it > > > > > > > > > > > > > > into > > > > > > > > > > > > > > DK_WARNING > > > > > > > > > > > > > > or DK_ERROR in diagnostic_impl. > > > > > > > > > > > > > > > > > > > > > > > > > > > > But we could still set diagnostic- > > > > > > > > > > > > > > >option_index even for > > > > > > > > > > > > > > DK_ERROR, > > > > > > > > > > > > > > whether to > > > > > > > > > > > > > > context->m_opt_permissive or to its own > > > > > > > > > > > > > > warning flag, > > > > > > > > > > > > > > perhaps > > > > > > > > > > > > > > -Wno-template-body? > > > > > > > > > > > > > > > > > > > > > > > > > > Fixed by adding an enabled-by-default - > > > > > > > > > > > > > Wtemplate-body flag > > > > > > > > > > > > > and > > > > > > > > > > > > > setting > > > > > > > > > > > > > option_index to it for each downgraded > > > > > > > > > > > > > error. Thus > > > > > > > > > > > > > -permissive > > > > > > > > > > > > > -Wno-template-body would suppress the > > > > > > > > > > > > > downgraded warnings > > > > > > > > > > > > > entirely, > > > > > > > > > > > > > and > > > > > > > > > > > > > only issue a generic error upon instantiation > > > > > > > > > > > > > of the > > > > > > > > > > > > > erroneous > > > > > > > > > > > > > template. > > > > > > > > > > > > > > > > > > > > > > > > ... or did you have in mind to set option_index > > > > > > > > > > > > even when > > > > > > > > > > > > not > > > > > > > > > > > > using > > > > > > > > > > > > -fpermissive so that eligible non-downgraded > > > > > > > > > > > > errors get the > > > > > > > > > > > > [-fpermissive] or [-Wtemplate-body] hint as > > > > > > > > > > > > well? > > > > > > > > > > > > > > > > > > > > > > Yes. > > > > > > > > > > > > > > > > > > > > > > > IMHO I'm not sure that'd be worth the extra > > > > > > > > > > > > noise since the > > > > > > > > > > > > vast > > > > > > > > > > > > majority of users appreciate and expect errors > > > > > > > > > > > > to get > > > > > > > > > > > > diagnosed > > > > > > > > > > > > inside > > > > > > > > > > > > templates. > > > > > > > > > > > > > > > > > > > > > > But people trying to build legacy code should > > > > > > > > > > > appreciate the > > > > > > > > > > > pointer > > > > > > > > > > > for > > > > > > > > > > > how > > > > > > > > > > > to make it compile, as with other permerrors. > > > > > > > > > > > > > > > > > > > > > > > And on second thought I'm not sure what extra > > > > > > > > > > > > value a new > > > > > > > > > > > > warning > > > > > > > > > > > > flag > > > > > > > > > > > > adds either. I can't think of a good reason > > > > > > > > > > > > why one would > > > > > > > > > > > > use > > > > > > > > > > > > -fpermissive -Wno-template-body? > > > > > > > > > > > > > > > > > > > > > > One would use -Wno-template-body (or -Wno- > > > > > > > > > > > error=template-body) > > > > > > > > > > > without > > > > > > > > > > > -fpermissive, like with the various permerror_opt > > > > > > > > > > > cases. > > > > > > > > > > > > > > > > > > > > Since compiling legacy/unmaintained code is the > > > > > > > > > > only plausible > > > > > > > > > > use > > > > > > > > > > case, > > > > > > > > > > why have a dedicated warning flag instead of just > > > > > > > > > > recommending > > > > > > > > > > -fpermissive > > > > > > > > > > when compiling legacy code? I don't quite > > > > > > > > > > understand the > > > > > > > > > > motivation > > > > > > > > > > for > > > > > > > > > > adding a new permerror_opt flag for this class of > > > > > > > > > > errors. > > > > > > > > > > > > > > > > > > It seems to me an interesting class of errors, but I > > > > > > > > > don't mind > > > > > > > > > leaving it > > > > > > > > > under just -fpermissive if you prefer. > > > > > > > > > > > > > > > > > > > -Wnarrowing is an existing permerror_opt flag, but > > > > > > > > > > I can imagine > > > > > > > > > > it's > > > > > > > > > > useful to pass -Wno-error=narrowing etc when > > > > > > > > > > incrementally > > > > > > > > > > migrating > > > > > > > > > > C / C++98 code to modern C++ where you don't want > > > > > > > > > > any > > > > > > > > > > conformance > > > > > > > > > > errors > > > > > > > > > > allowed by -fpermissive to sneak in. So being able > > > > > > > > > > to narrowly > > > > > > > > > > control > > > > > > > > > > this class of errors seems useful, so a dedicated > > > > > > > > > > flag makes > > > > > > > > > > sense. > > > > > > > > > > > > > > > > > > > > But there's no parallel for -Wtemplate-body here, > > > > > > > > > > since by > > > > > > > > > > assumption > > > > > > > > > > the code base is unmaintained / immutable. > > > > > > > > > > Otherwise the more > > > > > > > > > > proper > > > > > > > > > > fix would be to just fix and/or delete the > > > > > > > > > > uninstantiated > > > > > > > > > > erroneous > > > > > > > > > > template. If say you're #including a legacy header > > > > > > > > > > that has > > > > > > > > > > such > > > > > > > > > > errors, then doing #pragma GCC diagnostic "- > > > > > > > > > > fpermissive -w" > > > > > > > > > > around > > > > > > > > > > the #include should be totally fine too. > > > > > > > > > > > > > > > > I just realized #pragma GCC diagnostic warning "- > > > > > > > > fpermissive" etc > > > > > > > > doesn't actually work since -fpermissive isn't a > > > > > > > > warning flag. So > > > > > > > > having a dedicated flag for the class of errors has at > > > > > > > > least one > > > > > > > > clear > > > > > > > > benefit -- we can use #pragmas to selectively disable > > > > > > > > the errors > > > > > > > > now. > > > > > > > > > > > > > > > > > > > > > > > > > > > > I just don't see the use case for being able to > > > > > > > > > > narrowly control > > > > > > > > > > this > > > > > > > > > > class of errors that justifies the extra > > > > > > > > > > implementation > > > > > > > > > > complexity > > > > > > > > > > (specifically for properly detecting -Wno- > > > > > > > > > > error=template-body in > > > > > > > > > > the > > > > > > > > > > callback hook)? > > > > > > > > > > > > > > > > > > The hook shouldn't need to do anything special; > > > > > > > > > report_diagnostic > > > > > > > > > handles > > > > > > > > > -Wno-error=whatever. > > > > > > > > > > > > > > > > The issue was that the callback has to know in advance > > > > > > > > whether > > > > > > > > -Wno-error=template-body is active so that it can flag > > > > > > > > the template > > > > > > > > as > > > > > > > > having a relaxed error. Checking !warning_enabled_at > > > > > > > > wasn't enough > > > > > > > > because it will return true even for -Wno- > > > > > > > > error=template-body. I > > > > > > > > think we just need to check diagnostic_enabled > > > > > > > > directly, like so? > > > > > > > > > > > > > > Why not always flag it? It doesn't seem harmful to give > > > > > > > the > > > > > > > "instatiating > > > > > > > erroneous template" error later even if we gave a hard > > > > > > > error during > > > > > > > parsing. > > > > > > > > > > > > Hmm, it just seems redundant to me I guess? The reason we > > > > > > need the > > > > > > "instantiating erroneous template" error is to ensure that > > > > > > _some_ error > > > > > > was issued rendering the TU ill-formed when an erroneous > > > > > > template gets > > > > > > instantiated. If parse-time errors are hard errors then > > > > > > this is > > > > > > guaranteed, but it's not if we're downgrading such errors. > > > > > > > > > > Yes, it's redundant, but avoiding it doesn't seem worth > > > > > duplicating all > > > > > the > > > > > logic to determine whether it will be an error or not. > > > > > > > > > > Simpler might be to skip the "instantiating" error if > > > > > seen_error()? > > > > > > > > Sure. This makes the expected diagnostics in the -Wno- > > > > template-body > > > > testcase a bit lacking since there's three instantiated > > > > templates with > > > > one logical error each, but only the first error is diagnosed. > > > > But I > > > > don't particularly mind that. > > > > > > > > > > > > > > > On that note it just occurred to me that we don't need to > > > > > > abort > > > > > > instantiation after the "instantiating erroneous template" > > > > > > error -- > > > > > > for sake of error recovery we can proceed to instantiate as > > > > > > if we > > > > > > issued a hard error at parse time. > > > > > > > > > > Agreed. > > > > > > > > > > Jason > > > > > > > > > > > > > > > > > > -- >8 -- > > > > > > > > Subject: [PATCH] c++: permit errors inside uninstantiated > > > > templates > > > > [PR116064] > > > > > > > > In recent versions of GCC we've been diagnosing more and more > > > > kinds of > > > > errors inside a template ahead of time. This is a largely good > > > > thing > > > > because it catches bugs, typos, dead code etc sooner. > > > > > > > > But if the template never gets instantiated then such errors > > > > are harmless > > > > and can be inconvenient to work around if say the code in > > > > question is > > > > third party and in maintenance mode. So it'd be handy to be > > > > able to > > > > prevent these template errors from rendering the entire TU > > > > uncompilable. > > > > (Note that such code is "ill-formed no diagnostic required" > > > > according > > > > the standard.) > > > > > > > > To that end this patch turns any errors issued within a > > > > template into > > > > premerrors associated with a new -Wtemplate-body flag so that > > > > they can > > > > > > perm > > > > > > > be downgraded via e.g. -fpermissive or -Wno-template=template- > > > > body. If > > > > the template containing a downgraded error later needs to be > > > > instantiated, > > > > we'll issue an error then. But if the template never gets > > > > instantiated > > > > then the downgraded error won't affect validity of the rest of > > > > the TU. > > > > > > > > This is implemented via a diagnostic hook that gets called for > > > > each > > > > diagnostic, and which adjusts an error diagnostic if we detect > > > > it's > > > > occurring from a template context and additionally flags this > > > > template > > > > context as erroneous. > > > > > > > > As an example, permissive-error1a.C gives: > > > > > > > > gcc/testsuite/g++.dg/template/permissive-error1a.C: In function > > > > 'void f()': > > > > gcc/testsuite/g++.dg/template/permissive-error1a.C:7:5: > > > > warning: increment > > > > of read-only variable 'n' [-Wtemplate-body] > > > > 7 | ++n; > > > > | ^ > > > > ... > > > > gcc/testsuite/g++.dg/template/permissive-error1a.C: In > > > > instantiation of > > > > 'void f() [with T = int]': > > > > gcc/testsuite/g++.dg/template/permissive-error1a.C:26:9: > > > > required from > > > > here > > > > 26 | f<int>(); > > > > | ~~~~~~^~ > > > > gcc/testsuite/g++.dg/template/permissive-error1a.C:5:6: error: > > > > instantiating > > > > erroneous template pattern > > > > > > Drop "pattern" here too. > > > > Fixed > > > > > > > > > 5 | void f() { > > > > | ^ > > > > gcc/testsuite/g++.dg/template/permissive-error1a.C:7:5: note: > > > > first error > > > > appeared here > > > > 7 | ++n; // { > > > > | ^ > > > > ... > > > > > > What happens if we compile an interface/header unit with an > > > erroneous > > > uninstantiated template? I'd probably reject such a module > > > rather than write > > > out the erroneity. Possibly just if the template isn't > > > discarded, not sure if > > > that distinction is too much trouble to bother with. > > > > I think it's good enough to uniformly reject the module given how > > small > > the intersection -fpermissive and modules users is, I imagine. > > > > > > > > > PR c++/116064 > > > > > > > > gcc/c-family/ChangeLog: > > > > > > > > * c.opt (Wtemplate-body): New warning. > > > > > > > > gcc/cp/ChangeLog: > > > > > > > > * cp-tree.h (erroneous_templates_t): Declare. > > > > (erroneous_templates): Declare. > > > > (cp_seen_error): Declare. > > > > (basic_seen_error): Define as alias to existing > > > > seen_error. > > > > > > Or we could use (seen_error)() where we mean the basic one? > > > > Sure, changed. > > > > > > > > > (seen_error): #define to cp_seen_error. > > > > * error.cc (get_current_template): Define. > > > > (relaxed_template_errors): Define. > > > > (cp_adjust_diagnostic_info): Define. > > > > (cp_seen_error): Define. > > > > (cxx_initialize_diagnostics): Set > > > > diagnostic_context::m_adjust_diagnostic_info. > > > > * pt.cc (instantiate_class_template): Issue a hard > > > > error > > > > when trying to instantiate a template pattern > > > > containing > > > > a permissively downgraded error. > > > > (instantiate_decl): Likewise. > > > > > > > > gcc/ChangeLog: > > > > > > > > * diagnostic.cc (diagnostic_context::initialize): Set > > > > m_adjust_diagnostic_info. > > > > (diagnostic_context::report_diagnostic): Call > > > > m_adjust_diagnostic_info. > > > > * diagnostic.h > > > > (diagnostic_context::diagnostic_enabled): Make > > > > public. > > > > > > You shouldn't need this change now? > > > > Oops, removed. > > > > > > > > > +static void > > > > +cp_adjust_diagnostic_info (diagnostic_context *context, > > > > + diagnostic_info *diagnostic) > > > > +{ > > > > + if (diagnostic->kind == DK_ERROR) > > > > + if (tree tmpl = get_current_template ()) > > > > + { > > > > + diagnostic->option_index = OPT_Wtemplate_body; > > > > + > > > > + if (context->m_permissive) > > > > + diagnostic->kind = DK_WARNING; > > > > + > > > > + if (!erroneous_templates) > > > > + erroneous_templates = new erroneous_templates_t; > > > > + if (!erroneous_templates->get (tmpl)) > > > > + { > > > > + /* Remember that this template had a parse-time > > > > error so > > > > + that we'll ensure a hard error has been issued > > > > upon > > > > + its instantiation. */ > > > > + location_t error_loc = diagnostic->richloc->get_loc > > > > (); > > > > + erroneous_templates->put (tmpl, error_loc); > > > > > > Instead of get+put you could use the get return value to store > > > error_loc? > > > > We need to use get_or_insert if we want to combine the two lookups. > > I went ahead and used hash_map_safe_get_or_insert here to get rid > > of the construction boilerplate as well. > > > > > > > > > +@opindex Wtemplate-body > > > > +@opindex Wno-template-body > > > > +@item -Wno-template-body @r{(C++ and Objective-C++ only)} > > > > +Disable diagnosing errors when parsing a template, and instead > > > > issue an > > > > +error only upon instantiation of the template. This flag can > > > > also be > > > > +used to downgrade such errors into warnings with @option{Wno- > > > > error=} or > > > > +@option{-fpermissive}. > > > > > > Please also refer to this flag in the -fpermissive documentation. > > > > Done. > > > > -- >8 -- > > > > Subject: [PATCH] c++: permit errors inside uninstantiated templates > > [PR116064] > > > > In recent versions of GCC we've been diagnosing more and more kinds > > of > > errors inside a template ahead of time. This is a largely good > > thing > > because it catches bugs, typos, dead code etc sooner. > > > > But if the template never gets instantiated then such errors are > > harmless > > and can be inconvenient to work around if say the code in question > > is > > third party and in maintenance mode. So it'd be handy to be able > > to > > prevent these template errors from rendering the entire TU > > uncompilable. > > (Note that such code is "ill-formed no diagnostic required" > > according > > the standard.) > > > > To that end this patch turns any errors issued within a template > > into > > permerrors associated with a new -Wtemplate-body flag so that they > > can > > be downgraded via e.g. -fpermissive or -Wno-template=template- > > body. If > > the template containing a downgraded error later needs to be > > instantiated, > > we'll issue an error then. But if the template never gets > > instantiated > > then the downgraded error won't affect validity of the rest of the > > TU. > > > > This is implemented via a diagnostic hook that gets called for each > > diagnostic, and which adjusts an error diagnostic if we detect it's > > occurring from a template context and additionally flags this > > template > > context as erroneous. > > > > As an example, permissive-error1a.C gives: > > > > gcc/testsuite/g++.dg/template/permissive-error1a.C: In function > > 'void f()': > > gcc/testsuite/g++.dg/template/permissive-error1a.C:7:5: warning: > > increment of read-only variable 'n' [-Wtemplate-body] > > 7 | ++n; > > | ^ > > ... > > gcc/testsuite/g++.dg/template/permissive-error1a.C: In > > instantiation of 'void f() [with T = int]': > > gcc/testsuite/g++.dg/template/permissive-error1a.C:26:9: required > > from here > > 26 | f<int>(); > > | ~~~~~~^~ > > gcc/testsuite/g++.dg/template/permissive-error1a.C:5:6: error: > > instantiating erroneous template > > 5 | void f() { > > | ^ > > gcc/testsuite/g++.dg/template/permissive-error1a.C:7:5: note: first > > error appeared here > > 7 | ++n; // { > > | ^ > > ... > > > > PR c++/116064 > > > > gcc/c-family/ChangeLog: > > > > * c.opt (Wtemplate-body): New warning. > > > > gcc/cp/ChangeLog: > > > > * cp-tree.h (erroneous_templates_t): Declare. > > (erroneous_templates): Declare. > > (cp_seen_error): Declare. > > (seen_error): #define to cp_seen_error. > > * error.cc (get_current_template): Define. > > (relaxed_template_errors): Define. > > (cp_adjust_diagnostic_info): Define. > > (cp_seen_error): Define. > > (cxx_initialize_diagnostics): Set > > diagnostic_context::m_adjust_diagnostic_info. > > * module.cc (finish_module_processing): Don't write the > > module if it contains an erroneous template. > > * pt.cc (instantiate_class_template): Issue a hard error > > when trying to instantiate a template containing a > > permissively downgraded error. > > (instantiate_decl): Likewise. > > > > gcc/ChangeLog: > > > > * diagnostic.cc (diagnostic_context::initialize): Set > > m_adjust_diagnostic_info. > > (diagnostic_context::report_diagnostic): Call > > m_adjust_diagnostic_info. > > * diagnostic.h > > (diagnostic_context::m_adjust_diagnostic_info): > > New data member. > > * doc/invoke.texi (-Wno-template-body): Document. > > (-fpermissive): Mention -Wtemplate-body. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/ext/typedef-init.C: Downgrade error inside > > template > > to warning due to -fpermissive. > > * g++.dg/pr84492.C: Likewise. > > * g++.old-deja/g++.pt/crash51.C: Remove unneeded dg- > > options. > > * g++.dg/template/permissive-error1.C: New test. > > * g++.dg/template/permissive-error1a.C: New test. > > * g++.dg/template/permissive-error1b.C: New test. > > * g++.dg/template/permissive-error1c.C: New test. > > --- > > gcc/c-family/c.opt | 4 ++ > > gcc/cp/cp-tree.h | 7 ++ > > gcc/cp/error.cc | 67 > > +++++++++++++++++++ > > gcc/cp/module.cc | 5 +- > > gcc/cp/pt.cc | 24 +++++++ > > gcc/diagnostic.cc | 4 ++ > > gcc/diagnostic.h | 4 ++ > > gcc/doc/invoke.texi | 12 +++- > > gcc/testsuite/g++.dg/ext/typedef-init.C | 2 +- > > gcc/testsuite/g++.dg/pr84492.C | 4 +- > > .../g++.dg/template/permissive-error1.C | 20 ++++++ > > .../g++.dg/template/permissive-error1a.C | 31 +++++++++ > > .../g++.dg/template/permissive-error1b.C | 30 +++++++++ > > .../g++.dg/template/permissive-error1c.C | 31 +++++++++ > > gcc/testsuite/g++.old-deja/g++.pt/crash51.C | 1 - > > 15 files changed, 240 insertions(+), 6 deletions(-) > > create mode 100644 gcc/testsuite/g++.dg/template/permissive- > > error1.C > > create mode 100644 gcc/testsuite/g++.dg/template/permissive- > > error1a.C > > create mode 100644 gcc/testsuite/g++.dg/template/permissive- > > error1b.C > > create mode 100644 gcc/testsuite/g++.dg/template/permissive- > > error1c.C > > > > diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt > > index a52682d835c..44117ba713c 100644 > > --- a/gcc/c-family/c.opt > > +++ b/gcc/c-family/c.opt > > @@ -1420,6 +1420,10 @@ Wtautological-compare > > C ObjC C++ ObjC++ Var(warn_tautological_compare) Warning > > LangEnabledBy(C ObjC C++ ObjC++,Wall) > > Warn if a comparison always evaluates to true or false. > > > > +Wtemplate-body > > +C++ ObjC++ Var(warn_template_body) Warning Init(1) > > +Diagnose errors when parsing a template. > > + > > Wtemplate-id-cdtor > > C++ ObjC++ Var(warn_template_id_cdtor) Warning > > Warn about simple-template-id in a constructor or destructor. > > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h > > index 238d786b067..08ee5895c6a 100644 > > --- a/gcc/cp/cp-tree.h > > +++ b/gcc/cp/cp-tree.h > > @@ -7190,6 +7190,13 @@ extern location_t > > location_of (tree); > > extern void qualified_name_lookup_error (tree, > > tree, tree, > > location_t); > > > > +using erroneous_templates_t > > + = hash_map<tree, location_t, > > simple_hashmap_traits<tree_decl_hash, location_t>>; > > +extern erroneous_templates_t *erroneous_templates; > > + > > +extern bool cp_seen_error (); > > +#define seen_error() cp_seen_error() > > + > > /* in except.cc */ > > extern void init_terminate_fn (void); > > extern void init_exception_processing (void); > > diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc > > index d80bac822ba..7eab0bf76b4 100644 > > --- a/gcc/cp/error.cc > > +++ b/gcc/cp/error.cc > > @@ -165,6 +165,72 @@ class cxx_format_postprocessor : public > > format_postprocessor > > deferred_printed_type m_type_b; > > }; > > > > +/* Return the in-scope template that's currently being parsed, or > > + NULL_TREE otherwise. */ > > + > > +static tree > > +get_current_template () > > +{ > > + if (scope_chain && in_template_context && !current_instantiation > > ()) > > + if (tree ti = get_template_info (current_scope ())) > > + return TI_TEMPLATE (ti); > > + > > + return NULL_TREE; > > +} > > + > > +/* A map from TEMPLATE_DECLs that we've determined to be erroneous > > + at parse time to the location of the first error within. */ > > + > > +erroneous_templates_t *erroneous_templates; > > + > > +/* Callback function diagnostic_context::m_adjust_diagnostic_info. > > + > > + Errors issued when parsing a template are automatically treated > > like > > + permerrors associated with the -Wtemplate-body flag and can be > > + downgraded into warnings accordingly, in which case we'll still > > + issue an error if we later need to instantiate the template. > > */ > > + > > +static void > > +cp_adjust_diagnostic_info (diagnostic_context *context, > > + diagnostic_info *diagnostic) > > +{ > > + if (diagnostic->kind == DK_ERROR) > > + if (tree tmpl = get_current_template ()) > > + { > > + diagnostic->option_index = OPT_Wtemplate_body; > > + > > + if (context->m_permissive) > > + diagnostic->kind = DK_WARNING; > > + > > + bool existed; > > + location_t &error_loc > > + = hash_map_safe_get_or_insert<false> > > (erroneous_templates, > > + tmpl, &existed); > > + if (!existed) > > + /* Remember that this template had a parse-time error so > > + that we'll ensure a hard error has been issued upon > > + its instantiation. */ > > + error_loc = diagnostic->richloc->get_loc (); > > + } > > +} > > + > > +/* A generalization of seen_error which also returns true if we've > > + permissively downgraded an error to a warning inside a > > template. */ > > + > > +bool > > +cp_seen_error () > > +{ > > + if ((seen_error) ()) > > + return true; > > + > > + if (erroneous_templates) > > + if (tree tmpl = get_current_template ()) > > + if (erroneous_templates->get (tmpl)) > > + return true; > > + > > + return false; > > +} > > + > > /* CONTEXT->printer is a basic pretty printer that was > > constructed > > presumably by diagnostic_initialize(), called early in the > > compiler's initialization process (in general_init) Before the > > FE > > @@ -187,6 +253,7 @@ cxx_initialize_diagnostics (diagnostic_context > > *context) > > diagnostic_starter (context) = cp_diagnostic_starter; > > /* diagnostic_finalizer is already c_diagnostic_finalizer. */ > > diagnostic_format_decoder (context) = cp_printer; > > + context->m_adjust_diagnostic_info = cp_adjust_diagnostic_info; > > pp_format_postprocessor (pp) = new cxx_format_postprocessor (); > > } > > > > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc > > index d1607a06757..7130faf26f5 100644 > > --- a/gcc/cp/module.cc > > +++ b/gcc/cp/module.cc > > @@ -20768,7 +20768,10 @@ finish_module_processing (cpp_reader > > *reader) > > > > cookie = new module_processing_cookie (cmi_name, tmp_name, > > fd, e); > > > > - if (errorcount) > > + if (errorcount > > + /* Don't write the module if it contains an erroneous > > template. */ > > + || (erroneous_templates > > + && !erroneous_templates->is_empty ())) > > warning_at (state->loc, 0, "not writing module %qs due to > > errors", > > state->get_flatname ()); > > else if (cookie->out.begin ()) > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > > index 77fa5907c3d..b83922a530d 100644 > > --- a/gcc/cp/pt.cc > > +++ b/gcc/cp/pt.cc > > @@ -12376,6 +12376,18 @@ instantiate_class_template (tree type) > > if (! push_tinst_level (type)) > > return type; > > > > + if (erroneous_templates && !(seen_error) ()) > > + if (location_t *error_loc = erroneous_templates->get (templ)) > > + { > > + /* We're trying to instantiate a template pattern > > containing > > + an error that we've permissively downgraded to a > > warning. > > + Issue a hard error now to ensure the TU is considered > > + ill-formed. */ > > + location_t decl_loc = location_of (templ); > > + error_at (decl_loc, "instantiating erroneous template"); > > + inform (*error_loc, "first error appeared here"); > > + }
I confess I haven't been paying proper attention to this thread - sorry, but please can you add an auto_diagnostic_group d; before the "error_at", so that the "inform" is assocated with it. Thanks Dave > > Let's factor this out instead of repeating it. OK with that change. > > Jason >