Message ID | 5203F75A.9080206@oracle.com |
---|---|
State | New |
Headers | show |
On 08/08/2013 03:54 PM, Paolo Carlini wrote: > the really interesting one is decltype28.C, which we don't reject > anymore, we simply accept it. What is happening is that the overload > which leads to excessive template instantiation depth is SFINAE-ed away > and the other one "wins"! Thus, this is the core of my message: it seems > that we behave wrt this issue - SFINAE vs template instantiation depth - > in a different way vs current clang++ and icc: we produce hard error > messages in SFINAE contexts. Is that intended? Yes, that is intended. Changing that could mean that the meaning of code depends on what max depth the user selected. Jason
Hi, >Yes, that is intended. Changing that could mean that the meaning of >code depends on what max depth the user selected. Indeed. Yesterday I wondered what would happen if the front-end had a way to detect, in some very specific and special cases only of course, really infinite recursions, in the sense that no increase in the depth would "cure" them. Would it be ok in that case to sfinae away? Paolo
.. another thought I had, less esoteric ;) is the following: we use tf_none for two rather different reasons: for SFINAE and to avoid recursive Error routines calls, when we call tsubst (... tf_none, ...) from dump_template_bindings. I understand, given your reply, that in general in the first case, thus SFINAE, we should avoid all hard errors *but* the one about too deep recursions (barring some sort of powerful infinite recursion detector). What about the second case, however? Should it be different? An error message is being produced in any case, for a reason or another, it shouldn't be prevented or made more difficult only because there is deep recursion somewhere. I think that in that second case we should suppress the error message about too deep recursion too. But how to tell it apart? Looks like we want some sort of separate tf_*, a tf_in_diagnostic, or something, very similar to tf_none, but truly with no exceptions. Actually this vague idea occured to me a number of times, I think having that would help in a number of situations. What do you think? Thanks, Paolo. (*) Maybe there is third one, like in some recent tweaks Jakub did, but let's leave it alone here.
On 08/09/2013 08:43 AM, Paolo Carlini wrote: >> Yes, that is intended. Changing that could mean that the meaning of >> code depends on what max depth the user selected. > > Indeed. Yesterday I wondered what would happen if the front-end had a way to detect, in some very specific and special cases only of course, really infinite recursions, in the sense that no increase in the depth would "cure" them. Would it be ok in that case to sfinae away? Eh, hopefully not. Otherwise, program behavior would depend on how well the compiler solves the halting problem. It's interesting question, but hopefully we can make all errors due to exceeded implementation limits hard errors, not subject to SFINAE.
Hi, Florian Weimer <fweimer@redhat.com> ha scritto: >On 08/09/2013 08:43 AM, Paolo Carlini wrote: > >>> Yes, that is intended. Changing that could mean that the meaning of >>> code depends on what max depth the user selected. >> >> Indeed. Yesterday I wondered what would happen if the front-end had a >way to detect, in some very specific and special cases only of course, >really infinite recursions, in the sense that no increase in the depth >would "cure" them. Would it be ok in that case to sfinae away? > >Eh, hopefully not. Otherwise, program behavior would depend on how >well >the compiler solves the halting problem. I see. You know, I was trying to figure out the logic other compilers - two of them, actually - are following, because the really appear to sfinae away infinite recursions. Was trying to imagine cases in which it would be safe. Paolo
On 08/09/2013 09:28 AM, Paolo Carlini wrote:
> I see. You know, I was trying to figure out the logic other compilers - two of them, actually - are following, because the really appear to sfinae away infinite recursions. Was trying to imagine cases in which it would be safe.
Could their behavior just be bugs? Depending on their error recovery
implementation, not flagging infinite recursion as a hard error in
SFINAE context could be an easy mistake to make.
Hi, Florian Weimer <fweimer@redhat.com> ha scritto: >Could their behavior just be bugs? Depending on their error recovery >implementation, not flagging infinite recursion as a hard error in >SFINAE context could be an easy mistake to make. Sure can be. In a sense, as I tried to explain in another sub-thread, we do have the complementary one. Paolo
On Thu, Aug 8, 2013 at 6:40 PM, Jason Merrill <jason@redhat.com> wrote: > On 08/08/2013 03:54 PM, Paolo Carlini wrote: >> >> the really interesting one is decltype28.C, which we don't reject >> anymore, we simply accept it. What is happening is that the overload >> which leads to excessive template instantiation depth is SFINAE-ed away >> and the other one "wins"! Thus, this is the core of my message: it seems >> that we behave wrt this issue - SFINAE vs template instantiation depth - >> in a different way vs current clang++ and icc: we produce hard error >> messages in SFINAE contexts. Is that intended? > > > Yes, that is intended. Changing that could mean that the meaning of code > depends on what max depth the user selected. that would be disturbing… -- gaby
On Fri, Aug 9, 2013 at 2:13 AM, Florian Weimer <fweimer@redhat.com> wrote: > On 08/09/2013 08:43 AM, Paolo Carlini wrote: > >>> Yes, that is intended. Changing that could mean that the meaning of >>> code depends on what max depth the user selected. >> >> >> Indeed. Yesterday I wondered what would happen if the front-end had a way >> to detect, in some very specific and special cases only of course, really >> infinite recursions, in the sense that no increase in the depth would "cure" >> them. Would it be ok in that case to sfinae away? > > > Eh, hopefully not. Otherwise, program behavior would depend on how well the > compiler solves the halting problem. > > It's interesting question, but hopefully we can make all errors due to > exceeded implementation limits hard errors, not subject to SFINAE. agreed. -- Gaby
On Fri, Aug 9, 2013 at 2:33 AM, Florian Weimer <fweimer@redhat.com> wrote: > On 08/09/2013 09:28 AM, Paolo Carlini wrote: > >> I see. You know, I was trying to figure out the logic other compilers - >> two of them, actually - are following, because the really appear to sfinae >> away infinite recursions. Was trying to imagine cases in which it would be >> safe. > > > Could their behavior just be bugs? Depending on their error recovery > implementation, not flagging infinite recursion as a hard error in SFINAE > context could be an easy mistake to make. Indeed. The fact we try to recreate template instantiations, as opposed to using what is already known at the point where we get the diagnostics is a worrisome aspect of our current infrastructure. That obviously manifests itself with the "error re-entered…" stuff. -- Gaby
On Fri, Aug 9, 2013 at 2:13 AM, Paolo Carlini <paolo.carlini@oracle.com> wrote: > .. another thought I had, less esoteric ;) is the following: we use tf_none > for two rather different reasons: for SFINAE and to avoid recursive Error > routines calls, when we call tsubst (... tf_none, ...) from > dump_template_bindings. > > I understand, given your reply, that in general in the first case, thus > SFINAE, we should avoid all hard errors *but* the one about too deep > recursions (barring some sort of powerful infinite recursion detector). What > about the second case, however? Should it be different? An error message is > being produced in any case, for a reason or another, it shouldn't be > prevented or made more difficult only because there is deep recursion > somewhere. I think that in that second case we should suppress the error > message about too deep recursion too. But how to tell it apart? Looks like > we want some sort of separate tf_*, a tf_in_diagnostic, or something, very > similar to tf_none, but truly with no exceptions. Actually this vague idea > occured to me a number of times, I think having that would help in a number > of situations. > > What do you think? > > Thanks, > Paolo. > > (*) Maybe there is third one, like in some recent tweaks Jakub did, but > let's leave it alone here. I think we should find ways to have the pretty printer in the diagnostic framework stop trying to redo most of the work done by the type checker. In its current form, that is fragile. -- Gaby
Hi, On 08/09/2013 10:46 AM, Gabriel Dos Reis wrote: > I think we should find ways to have the pretty printer in the > diagnostic framework stop trying to redo most of the work done by the > type checker. In its current form, that is fragile. -- Gaby Yeah. That tsubst (..., tf_none, ...) from dump_template_bindings, always seemed a little weird to me. Fact is, we have got quite a few serious diagnostic bugs where we print *very little* sensible before the Error reporting routines re-entered message. Like 54080 and 52875, but I'm sure there are more. Do you have any tips about a reasonable way to handle the latter in the short term? Thanks! Paolo.
On Fri, Aug 9, 2013 at 4:28 AM, Paolo Carlini <paolo.carlini@oracle.com> wrote: > Hi, > > > On 08/09/2013 10:46 AM, Gabriel Dos Reis wrote: >> >> I think we should find ways to have the pretty printer in the diagnostic >> framework stop trying to redo most of the work done by the type checker. In >> its current form, that is fragile. -- Gaby > > Yeah. That tsubst (..., tf_none, ...) from dump_template_bindings, always > seemed a little weird to me. Fact is, we have got quite a few serious > diagnostic bugs where we print *very little* sensible before the Error > reporting routines re-entered message. Like 54080 and 52875, but I'm sure > there are more. > > Do you have any tips about a reasonable way to handle the latter in the > short term? I arrived on the west coast with little sleep, and I can't find sleep just right now (and you may argue reading gcc list isn't a good way to find sleep either); let me think about it more. -- Gaby
Index: cp-tree.h =================================================================== --- cp-tree.h (revision 201588) +++ cp-tree.h (working copy) @@ -5541,7 +5541,7 @@ extern tree fold_non_dependent_expr_sfinae (tree, extern bool alias_type_or_template_p (tree); extern bool alias_template_specialization_p (const_tree); extern bool explicit_class_specialization_p (tree); -extern int push_tinst_level (tree); +extern int push_tinst_level (tree, tsubst_flags_t); extern void pop_tinst_level (void); extern struct tinst_level *outermost_tinst_level(void); extern void init_template_processing (void); Index: mangle.c =================================================================== --- mangle.c (revision 201588) +++ mangle.c (working copy) @@ -3429,7 +3429,7 @@ mangle_decl_string (const tree decl) { struct tinst_level *tl = current_instantiation (); if ((!tl || tl->decl != decl) - && push_tinst_level (decl)) + && push_tinst_level (decl, tf_warning_or_error)) { template_p = true; saved_fn = current_function_decl; Index: pt.c =================================================================== --- pt.c (revision 201588) +++ pt.c (working copy) @@ -6995,7 +6995,7 @@ add_pending_template (tree d) level = !current_tinst_level || current_tinst_level->decl != d; if (level) - push_tinst_level (d); + push_tinst_level (d, tf_warning_or_error); pt = ggc_alloc_pending_template (); pt->next = NULL; @@ -8021,24 +8021,28 @@ static GTY(()) struct tinst_level *last_error_tins for diagnostics and to restore it later. */ int -push_tinst_level (tree d) +push_tinst_level (tree d, tsubst_flags_t complain) { struct tinst_level *new_level; if (tinst_depth >= max_tinst_depth) { last_error_tinst_level = current_tinst_level; - if (TREE_CODE (d) == TREE_LIST) - error ("template instantiation depth exceeds maximum of %d (use " - "-ftemplate-depth= to increase the maximum) substituting %qS", - max_tinst_depth, d); - else - error ("template instantiation depth exceeds maximum of %d (use " - "-ftemplate-depth= to increase the maximum) instantiating %qD", - max_tinst_depth, d); - print_instantiation_context (); + if (complain & tf_error) + { + if (TREE_CODE (d) == TREE_LIST) + error ("template instantiation depth exceeds maximum of %d (use " + "-ftemplate-depth= to increase the maximum) " + "substituting %qS", max_tinst_depth, d); + else + error ("template instantiation depth exceeds maximum of %d (use " + "-ftemplate-depth= to increase the maximum) " + "instantiating %qD", max_tinst_depth, d); + print_instantiation_context (); + } + return 0; } @@ -8691,7 +8695,7 @@ instantiate_class_template_1 (tree type) return type; /* If we've recursively instantiated too many templates, stop. */ - if (! push_tinst_level (type)) + if (! push_tinst_level (type, tf_warning_or_error)) return type; /* Now we're really doing the instantiation. Mark the type as in @@ -15005,7 +15009,7 @@ instantiate_alias_template (tree tmpl, tree args, if (tmpl == error_mark_node || args == error_mark_node) return error_mark_node; tree tinst = build_tree_list (tmpl, args); - if (!push_tinst_level (tinst)) + if (!push_tinst_level (tinst, complain)) { ggc_free (tinst); return error_mark_node; @@ -15219,7 +15223,7 @@ fn_type_unification (tree fn, } TREE_VALUE (tinst) = explicit_targs; - if (!push_tinst_level (tinst)) + if (!push_tinst_level (tinst, complain)) { excessive_deduction_depth = true; goto fail; @@ -15270,7 +15274,7 @@ fn_type_unification (tree fn, any errors (e.g. from class instantiations triggered by instantiation of default template arguments) come from. If we are explaining, this context is redundant. */ - if (!explain_p && !push_tinst_level (tinst)) + if (!explain_p && !push_tinst_level (tinst, complain)) { excessive_deduction_depth = true; goto fail; @@ -15327,7 +15331,7 @@ fn_type_unification (tree fn, substitution results in an invalid type, as described above, type deduction fails. */ TREE_VALUE (tinst) = targs; - if (!push_tinst_level (tinst)) + if (!push_tinst_level (tinst, complain)) { excessive_deduction_depth = true; goto fail; @@ -18876,7 +18880,7 @@ maybe_instantiate_noexcept (tree fn) if (TREE_CODE (noex) == DEFERRED_NOEXCEPT) { - if (push_tinst_level (fn)) + if (push_tinst_level (fn, tf_warning_or_error)) { push_access_scope (fn); push_deferring_access_checks (dk_no_deferred); @@ -19000,7 +19004,7 @@ instantiate_decl (tree d, int defer_ok, || spec == NULL_TREE); /* This needs to happen before any tsubsting. */ - if (! push_tinst_level (d)) + if (! push_tinst_level (d, tf_warning_or_error)) return d; timevar_push (TV_TEMPLATE_INST); Index: typeck2.c =================================================================== --- typeck2.c (revision 201588) +++ typeck2.c (working copy) @@ -1564,7 +1564,7 @@ build_x_arrow (location_t loc, tree expr, tsubst_f return error_mark_node; if (fn && DECL_USE_TEMPLATE (fn)) - push_tinst_level (fn); + push_tinst_level (fn, complain); fn = NULL; if (vec_member (TREE_TYPE (expr), types_memoized))