On Tue, Oct 22, 2019 at 11:20 AM Jakub Jelinek <ja...@redhat.com> wrote:
>
> On Tue, Oct 22, 2019 at 10:57:42AM -0400, Jason Merrill wrote:
> > > So, do you prefer to do it the other way during build_cxx_call?
> >
> > It seems more straightforward.
>
> Ok.
>
> > > The issues that need to be resolved are the default arguments,
> > > which from my understanding are not full expressions and thus for them we 
> > > do
> > > not know whether they will appear in immediate function context or not,
> > > so would we need some global flag (in_default_argument?) and just don't
> > > handle it in build_cxx_call if it is set, and then have something like
> > > cxx_eval_consteval in the recent patch invoked on the default arguments
> > > before adding it to function calls?
> >
> > It seems to me that an immediate invocation in a default argument is
> > not in immediate function context, so we can handle it normally.  The
> > only reason we need to handle immediate function context specially is
> > to allow uses of parameters of the immediate function in calls to
> > other immediate functions, and we can't refer to parameters in a
> > default argument anyway.
>
> Well, [expr.const]/(10.4) contains an example that requires it to work:
> consteval int f() { return 42; }
> consteval auto g() { return f; }
> consteval int h(int (*p)() = g()) { return p(); }
> constexpr int r = h(); // OK
> constexpr auto e = g(); // ill-formed: a pointer to an immediate function is
>                         // not a permitted result of a constant expression
> When parsing the g() expression as default argument, we don't know it will
> be a default argument of a consteval function.

g() is in immediate function context because h is consteval; clearly
we can't rely on current_function_decl for that.  The standard says
immediate function context is when "its innermost non-block scope is a
function parameter scope of an immediate function", which is the case
here.

> > > Wouldn't it affect also what constructors are invoked?  Say if some class
> > > has consteval constructor with int argument and non-consteval copy
> > > constructor:
> > > struct S { consteval S (int x) : s (x) {} S (const S &); int s; };
> > > should
> > > void foo () { S s = 5; }
> > > then invoke first the consteval ctor constructing some temporary and then
> > > the copy constructor?
> >
> > Yes, I think that follows.
>
> But in that case whether the temporary is created or not is no longer an
> implementation detail, so is it clear and can be clarified in the standard
> that a temporary must be created, so that other implementations will handle
> it the same?

Yes, I've already sent mail to the list.

Jason

Reply via email to