[C++ PATCH] Implement P1073R3: Immediate functions (PR c++/88335)

Jakub Jelinek jakub@redhat.com
Tue Oct 22 15:54:00 GMT 2019


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.  If g() is evaluated here
while parsing it, it would return address of consteval function, which is
invalid.

> > 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?

> > And last, wouldn't handling it in build_cxx_call already affect then
> > discarded statements?  The patch I posted today would most likely not
> > consteval evaluate much in discarded contexts, perhaps with the exception
> > of variable initializers.  But build_cxx_call is called even if
> > in_discarded_stmt, right?  Aren't some constant expressions evaluated even
> > in discarded statements though?
> > constexpr bool foo (int i) { if (i == 1) throw 1; return i == 0; }
> > template <typename T>
> > void
> > foo ()
> > {
> >   if constexpr (foo (2))
> >     {
> >       if constexpr (foo (1))
> >         ;
> >     }
> > }
> > so, shouldn't immediate functions be called too?
> 
> Yes, true.  I wasn't thinking of non-dependent discarded statements.

Though, if we don't go the build_cxx_call route, we'd then need to
cxx_eval_consteval the discarded expressions before we overwrite them to
NULL_TREE.

	Jakub



More information about the Gcc-patches mailing list