On June 10, 2016 6:15:25 PM GMT+02:00, Jason Merrill <ja...@redhat.com> wrote:
>On Fri, Jun 10, 2016 at 3:11 AM, Richard Biener <rguent...@suse.de>
>wrote:
>> On Thu, 9 Jun 2016, Jason Merrill wrote:
>>
>>> On Thu, Jun 9, 2016 at 3:39 AM, Richard Biener <rguent...@suse.de>
>wrote:
>>> > On Thu, 9 Jun 2016, Jakub Jelinek wrote:
>>> >
>>> >> On Thu, Jun 09, 2016 at 08:50:15AM +0200, Richard Biener wrote:
>>> >> > On Wed, 8 Jun 2016, Jason Merrill wrote:
>>> >> >
>>> >> > > On Wed, Jun 8, 2016 at 11:16 AM, Marc Glisse
><marc.gli...@inria.fr> wrote:
>>> >> > > > On Wed, 8 Jun 2016, Richard Biener wrote:
>>> >> > > >
>>> >> > > >> The following works around PR70992 but the issue came up
>repeatedly
>>> >> > > >> that we are not very consistent in preserving the
>undefined behavior
>>> >> > > >> of division or modulo by zero.  Ok - the only
>inconsistency is
>>> >> > > >> that we fold 0 % x to 0 but not 0 % 0 (with literal zero).
>>> >> > > >>
>>> >> > > >> After folding is now no longer done early in the C family
>FEs the
>>> >> > > >> number of diagnostic regressions with the patch below is
>two.
>>> >> > > >>
>>> >> > > >> FAIL: g++.dg/cpp1y/constexpr-sfinae.C  -std=c++14 (test
>for excess errors)
>>> >> > >
>>> >> > > Yep. We don't want to fold away undefined behavior in a
>constexpr
>>> >> > > function, since constexpr evaluation wants to detect
>undefined
>>> >> > > behavior and treat the expression as non-constant in that
>case.
>>> >> >
>>> >> > Hmm.  So 0 / x is not constant because x might be zero but 0 *
>x is
>>> >> > constant because it can never invoke undefined behavior?  Does
>this mean
>>> >> > that 0 << n is not const because n might be too large (I
>suppose
>>> >> > 0 << 12000 is not const already)?  Is 0 * (-x) const?  x might
>be INT_MIN.
>>> >>
>>> >> E.g. for the shifts the C++ FE has cxx_eval_check_shift_p which
>should
>>> >> optionally warn and/or set *non_constant_p.  0 * (-INT_MIN) would
>be
>>> >> non-constant too, etc.
>>> >> constexpr int foo (int x) { return -x; }
>>> >> constexpr int bar (int x) { return 0 * (-x); }
>>> >> constexpr int a = foo (-__INT_MAX__ - 1);
>>> >> constexpr int b = bar (-__INT_MAX__ - 1);
>>> >> shows that we don't diagnose the latter though, most likely
>because
>>> >> constexpr evaluation is done on the folded tree.
>>>
>>> I don't think there's any folding before constexpr evaluation in
>this
>>> case, since this doesn't involve a call.
>>>
>>> >> So, either whatever cp_fold does (which uses fold* underneath)
>should avoid
>>> >> folding such cases, or the constexpr evaluation should be done on
>a copy
>>> >> made before folding.  Then cp_fold doesn't have to prohibit
>optimizations
>>> >> and it is a matter of constexpr.c routines to detect all the
>undefined
>>> >> behavior.  After all, I think doing constexpr evaluation on
>unfolded trees
>>> >> will have also the advantage of better diagnostic locations.
>>> >
>>> > Yes, I think constexpr diagnostic / detection should be done on
>>> > unfolded trees (not sure why we'd need to a copy here, just do
>folding
>>> > later?).  If cp_fold already avoids folding 0 * (-x) then it
>should
>>> > simply avoid folding 0 / x or 0 % x as well (for the particular
>issue
>>> > this thread started on).
>>>
>>> The issue is with constexpr functions, which get delayed folding
>like
>>> any other function before they are used in constant expression
>>> evaluation.  The copy would be to preserve the unfolded trees
>through
>>> cp_fold_function.  I've been thinking about doing this anyway; this
>>> may be the motivation to go ahead with it.
>>
>> Or delay the folding until genericization - that is, after all
>parsing
>> is complete.  Not sure what this would do to memory usage or
>compile-time
>> when we keep all unfolded bodies (or even re-use them in template
>> instantiation).
>
>Genericization happens at the end of each (non-template) function, not
>at EOF.  Do you mean delay until gimplification?

Delay until after parsing, yes.

Richard.

>Jason


Reply via email to