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

2019-11-01 Thread Jason Merrill

On 11/1/19 5:19 PM, Jakub Jelinek wrote:

On Fri, Nov 01, 2019 at 09:56:44PM +0100, Jakub Jelinek wrote:

Ah, used 8.x to test it.  There have been r265787 and r269775 changes in
between.
Though
   auto d = [] () mutable __attribute__((noreturn)) constexpr {};
   auto e = [] () mutable [[noreturn]] constexpr {};
is still accepted.  I bet incorrectly though, I can try to fix it in a
follow-up patch, but can remove the attribute skipping from the consteval
patch then.


Perhaps like this (untested so far)?


Looks good.


Though, I have to wonder about the other callers of
cp_parser_decl_specifier_seq, whether attributes should be accepted anywhere
in between specifiers or not.


In a normal decl-specifier-seq it's fine to have attributes, just 
lambdas restrict the contents.



2019-11-01  Jakub Jelinek  

PR c++/89640
* parser.c (cp_parser_decl_specifier_seq): Don't parse attributes
if CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR.

* g++.dg/cpp1z/attr-lambda1.C: New test.
* g++.dg/ext/attr-lambda2.C: New test.

--- gcc/cp/parser.c.jj  2019-10-31 17:33:19.864518279 +0100
+++ gcc/cp/parser.c 2019-11-01 22:05:24.684037804 +0100
@@ -13965,7 +13965,8 @@ cp_parser_decl_specifier_seq (cp_parser*
if (!start_token)
start_token = token;
/* Handle attributes.  */
-  if (cp_next_tokens_can_be_attribute_p (parser))
+  if ((flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) == 0
+ && cp_next_tokens_can_be_attribute_p (parser))
{
  /* Parse the attributes.  */
  tree attrs = cp_parser_attributes_opt (parser);
--- gcc/testsuite/g++.dg/cpp1z/attr-lambda1.C.jj2019-11-01 
22:15:57.264378908 +0100
+++ gcc/testsuite/g++.dg/cpp1z/attr-lambda1.C   2019-11-01 22:16:11.143167034 
+0100
@@ -0,0 +1,12 @@
+// PR c++/89640
+// { dg-options "-Wno-attributes" }
+// { dg-do compile { target c++17 } }
+
+void test() {
+[]() mutable [[gnu::cold]] constexpr {}(); // { dg-error 
"expected" }
+[]() constexpr [[gnu::cold]] mutable {}(); // { dg-error 
"expected" }
+[]() [[gnu::cold]] mutable constexpr {}(); // { dg-error 
"expected" }
+[]() [[gnu::cold]] constexpr mutable {}(); // { dg-error 
"expected" }
+[]() mutable constexpr [[gnu::cold]] {}();
+[]() constexpr mutable [[gnu::cold]] {}();
+}
--- gcc/testsuite/g++.dg/ext/attr-lambda2.C.jj  2019-11-01 22:16:25.784943505 
+0100
+++ gcc/testsuite/g++.dg/ext/attr-lambda2.C 2019-11-01 22:16:42.736684714 
+0100
@@ -0,0 +1,12 @@
+// PR c++/89640
+// { dg-options "-Wno-attributes" }
+// { dg-do compile { target c++17 } }
+
+void test() {
+[]() mutable __attribute__((cold)) constexpr {}(); // { dg-error 
"expected" }
+[]() constexpr __attribute__((cold)) mutable {}(); // { dg-error 
"expected" }
+[]() __attribute__((cold)) mutable constexpr {}(); // { dg-error 
"expected" }
+[]() __attribute__((cold)) constexpr mutable {}(); // { dg-error 
"expected" }
+[]() mutable constexpr __attribute__((cold)) {}();
+[]() constexpr mutable __attribute__((cold)) {}();
+}


Jakub





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

2019-11-01 Thread Jakub Jelinek
On Fri, Nov 01, 2019 at 09:56:44PM +0100, Jakub Jelinek wrote:
> Ah, used 8.x to test it.  There have been r265787 and r269775 changes in
> between.
> Though
>   auto d = [] () mutable __attribute__((noreturn)) constexpr {};
>   auto e = [] () mutable [[noreturn]] constexpr {};
> is still accepted.  I bet incorrectly though, I can try to fix it in a
> follow-up patch, but can remove the attribute skipping from the consteval
> patch then.

Perhaps like this (untested so far)?
Though, I have to wonder about the other callers of
cp_parser_decl_specifier_seq, whether attributes should be accepted anywhere
in between specifiers or not.

2019-11-01  Jakub Jelinek  

PR c++/89640
* parser.c (cp_parser_decl_specifier_seq): Don't parse attributes
if CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR.

* g++.dg/cpp1z/attr-lambda1.C: New test.
* g++.dg/ext/attr-lambda2.C: New test.

--- gcc/cp/parser.c.jj  2019-10-31 17:33:19.864518279 +0100
+++ gcc/cp/parser.c 2019-11-01 22:05:24.684037804 +0100
@@ -13965,7 +13965,8 @@ cp_parser_decl_specifier_seq (cp_parser*
   if (!start_token)
start_token = token;
   /* Handle attributes.  */
-  if (cp_next_tokens_can_be_attribute_p (parser))
+  if ((flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) == 0
+ && cp_next_tokens_can_be_attribute_p (parser))
{
  /* Parse the attributes.  */
  tree attrs = cp_parser_attributes_opt (parser);
--- gcc/testsuite/g++.dg/cpp1z/attr-lambda1.C.jj2019-11-01 
22:15:57.264378908 +0100
+++ gcc/testsuite/g++.dg/cpp1z/attr-lambda1.C   2019-11-01 22:16:11.143167034 
+0100
@@ -0,0 +1,12 @@
+// PR c++/89640
+// { dg-options "-Wno-attributes" }
+// { dg-do compile { target c++17 } }
+
+void test() {
+[]() mutable [[gnu::cold]] constexpr {}(); // { dg-error 
"expected" }
+[]() constexpr [[gnu::cold]] mutable {}(); // { dg-error 
"expected" }
+[]() [[gnu::cold]] mutable constexpr {}(); // { dg-error 
"expected" }
+[]() [[gnu::cold]] constexpr mutable {}(); // { dg-error 
"expected" }
+[]() mutable constexpr [[gnu::cold]] {}();
+[]() constexpr mutable [[gnu::cold]] {}();
+}
--- gcc/testsuite/g++.dg/ext/attr-lambda2.C.jj  2019-11-01 22:16:25.784943505 
+0100
+++ gcc/testsuite/g++.dg/ext/attr-lambda2.C 2019-11-01 22:16:42.736684714 
+0100
@@ -0,0 +1,12 @@
+// PR c++/89640
+// { dg-options "-Wno-attributes" }
+// { dg-do compile { target c++17 } }
+
+void test() {
+[]() mutable __attribute__((cold)) constexpr {}(); // { dg-error 
"expected" }
+[]() constexpr __attribute__((cold)) mutable {}(); // { dg-error 
"expected" }
+[]() __attribute__((cold)) mutable constexpr {}(); // { dg-error 
"expected" }
+[]() __attribute__((cold)) constexpr mutable {}(); // { dg-error 
"expected" }
+[]() mutable constexpr __attribute__((cold)) {}();
+[]() constexpr mutable __attribute__((cold)) {}();
+}


Jakub



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

2019-11-01 Thread Jakub Jelinek
On Fri, Nov 01, 2019 at 04:42:45PM -0400, Jason Merrill wrote:
> It isn't accepted for me:
> 
> wa3.C: In function 'void foo()':
> wa3.C:4:29: warning: attribute ignored [-Wattributes]
> 4 |   auto a = [] () [[noreturn]] constexpr {};
>   | ^
> wa3.C:4:29: note: an attribute that appertains to a type-specifier is
> ignored
> wa3.C: In lambda function:
> wa3.C:4:31: error: expected '{' before 'constexpr'
> 4 |   auto a = [] () [[noreturn]] constexpr {};
>   |   ^
> wa3.C: In function 'void foo()':
> wa3.C:4:31: error: expected ',' or ';' before 'constexpr'
> wa3.C: In lambda function:
> wa3.C:5:44: error: expected '{' before 'constexpr'
> 5 |   auto b = [] () __attribute__((noreturn)) constexpr {};
>   |^
> wa3.C: In function 'void foo()':
> wa3.C:5:44: error: expected ',' or ';' before 'constexpr'
> 
> Moving constexpr before the attributes makes it compile.

Ah, used 8.x to test it.  There have been r265787 and r269775 changes in
between.
Though
  auto d = [] () mutable __attribute__((noreturn)) constexpr {};
  auto e = [] () mutable [[noreturn]] constexpr {};
is still accepted.  I bet incorrectly though, I can try to fix it in a
follow-up patch, but can remove the attribute skipping from the consteval
patch then.

> > The code should handle mutable consteval, as mutable is a keyword and it
> > will just keep looking after that keyword.
> 
> Ah, right.

Jakub



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

2019-11-01 Thread Jason Merrill

On 11/1/19 3:57 PM, Jakub Jelinek wrote:

On Fri, Nov 01, 2019 at 03:42:58PM -0400, Jason Merrill wrote:

+ for (size_t n = cp_parser_skip_balanced_tokens (parser, 1); ; n++)
+   {
+ size_t after = cp_parser_skip_attributes_opt (parser, n);
+ if (after > n)
+   {
+ n = after - 1;
+ continue;
+   }


You don't need to skip attributes, the decl-specifiers come immediately
after the ).


void
foo ()
{
   auto a = [] () [[noreturn]] constexpr {};
   auto b = [] () __attribute__((noreturn)) constexpr {};
   auto c = [] () mutable constexpr {};
}

(using constexpr instead of consteval to be able to test it without my
patch) is certainly accepted, not sure if that is conforming or not.


It isn't accepted for me:

wa3.C: In function 'void foo()':
wa3.C:4:29: warning: attribute ignored [-Wattributes]
4 |   auto a = [] () [[noreturn]] constexpr {};
  | ^
wa3.C:4:29: note: an attribute that appertains to a type-specifier is 
ignored

wa3.C: In lambda function:
wa3.C:4:31: error: expected '{' before 'constexpr'
4 |   auto a = [] () [[noreturn]] constexpr {};
  |   ^
wa3.C: In function 'void foo()':
wa3.C:4:31: error: expected ',' or ';' before 'constexpr'
wa3.C: In lambda function:
wa3.C:5:44: error: expected '{' before 'constexpr'
5 |   auto b = [] () __attribute__((noreturn)) constexpr {};
  |^
wa3.C: In function 'void foo()':
wa3.C:5:44: error: expected ',' or ';' before 'constexpr'

Moving constexpr before the attributes makes it compile.


The code should handle mutable consteval, as mutable is a keyword and it
will just keep looking after that keyword.


Ah, right.

Jason



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

2019-11-01 Thread Jakub Jelinek
On Fri, Nov 01, 2019 at 03:42:58PM -0400, Jason Merrill wrote:
> > + for (size_t n = cp_parser_skip_balanced_tokens (parser, 1); ; n++)
> > +   {
> > + size_t after = cp_parser_skip_attributes_opt (parser, n);
> > + if (after > n)
> > +   {
> > + n = after - 1;
> > + continue;
> > +   }
> 
> You don't need to skip attributes, the decl-specifiers come immediately
> after the ).

void
foo ()
{
  auto a = [] () [[noreturn]] constexpr {};
  auto b = [] () __attribute__((noreturn)) constexpr {};
  auto c = [] () mutable constexpr {};
}

(using constexpr instead of consteval to be able to test it without my
patch) is certainly accepted, not sure if that is conforming or not.

The grammar has
decl-specifier-seq[opt] after the ) in lambda-declarator and
decl-specifier-seq:
  decl-specifier attribute-specifier-seq[opt]
  decl-specifier decl-specifier-seq
so I'd say attribute-specifier-seq is only allowed at the very end of the
decl-specifier-seq, so maybe we have an accepts-invalid bug, but the
grammar doesn't cover the GNU attributes anyway.

> 
> OK with that change.
> 
> > + if (!cp_lexer_nth_token_is (parser->lexer, n, CPP_KEYWORD))
> > +   break;
> > + if (cp_lexer_peek_nth_token (parser->lexer, n)->keyword
> > + == RID_CONSTEVAL)
> 
> I suppose it's reasonable to not consider "mutable consteval" here.  :)
> 
> > +   {
> > + is_consteval = true;
> > + break;
> > +   }

The code should handle mutable consteval, as mutable is a keyword and it
will just keep looking after that keyword.

Jakub



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

2019-11-01 Thread Jason Merrill

On 10/31/19 1:21 PM, Jakub Jelinek wrote:

On Wed, Oct 30, 2019 at 05:06:00PM -0400, Jason Merrill wrote:

build_cplus_new does the magic of replacing a dummy argument, e.g.


   if (obj_arg && is_dummy_object (obj_arg))
 {
   call = build_cplus_new (DECL_CONTEXT (fndecl), call, complain);
   obj_arg = NULL_TREE;
 }


And then if the return value from build_special_member_call is
TREE_CONSTANT, we can return that directly from build_value_init rather than
look for an AGGR_INIT_EXPR.


Ok, that works.


Hmm, it shouldn't be hard to scan ahead to see if there's a consteval after
the parameter list.


Done it that way, we already have all the needed skip routines so nothing
really needs to be parsed, just skipped.

I've added some further tests and run into another issue, that for const
or constexpr vars with consteval ctor constexpr evaluation complained that
the ctor can't modify non-static data members in the object.  The problem
was that obj_arg passed in that case was *(S *) where var had const S
type, so had to add code to pass var in that case.

Bootstrapped/regtested on x86_64-linux and i686-linux, all tests pass now,
ok for trunk?

2019-10-31  Jakub Jelinek  

PR c++/88335 - Implement P1073R3: Immediate functions
c-family/
* c-common.h (enum rid): Add RID_CONSTEVAL.
* c-common.c (c_common_reswords): Add consteval.
cp/
* cp-tree.h (struct lang_decl_fn): Add immediate_fn_p bit.
(DECL_IMMEDIATE_FUNCTION_P, SET_DECL_IMMEDIATE_FUNCTION_P): Define.
(enum cp_decl_spec): Add ds_consteval.
(fold_non_dependent_expr): Add another tree argument defaulted to
NULL_TREE.
* name-lookup.h (struct cp_binding_level): Add immediate_fn_ctx_p
member.
* parser.c (cp_keyword_starts_decl_specifier_p): Adjust comments
for C++11 and C++20 specifiers.  Handle RID_CONSTEVAL.
(CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR): Adjust comment.
(CP_PARSER_FLAGS_CONSTEVAL): New.
(cp_parser_skip_balanced_tokens): New forward declaration.
(cp_parser_lambda_declarator_opt): Handle ds_consteval.  Set
current_binding_level->immediate_fn_ctx_p before parsing parameter
list if decl-specifier-seq contains consteval specifier.
(cp_parser_decl_specifier_seq): Handle RID_CONSTEVAL.
(cp_parser_explicit_instantiation): Diagnose explicit instantiation
with consteval specifier.
(cp_parser_init_declarator): For consteval or into flags
CP_PARSER_FLAGS_CONSTEVAL.
(cp_parser_direct_declarator): If CP_PARSER_FLAGS_CONSTEVAL, set
current_binding_level->immediate_fn_ctx_p in the sk_function_parms
scope.
(set_and_check_decl_spec_loc): Add consteval entry, formatting fix.
* call.c (build_addr_func): For direct calls to immediate functions
use build_address rather than decay_conversion.
(build_over_call): Evaluate immediate function invocations.
* error.c (dump_function_decl): Handle DECL_IMMEDIATE_FUNCTION_P.
* semantics.c (expand_or_defer_fn_1): Use tentative linkage and don't
call mark_needed for immediate functions.
* typeck.c (cxx_sizeof_or_alignof_expr): Likewise.  Formatting fix.
(cp_build_addr_expr_1): Reject taking address of immediate function
outside of immediate function.
* decl.c (validate_constexpr_redeclaration): Diagnose consteval
vs. non-consteval or vice versa redeclaration.  Use
SET_DECL_IMMEDIATE_FUNCTION_P if new_decl is immediate function.
(check_tag_decl): Use %qs with keyword string to simplify translation.
Handle ds_consteval.
(start_decl): Adjust diagnostics for static or thread_local variables
in immediate functions.
(grokfndecl): Call sorry_at on virtual consteval.  Use %qs with keyword
to string to simplify translation.  Diagnose consteval main.  Use
SET_DECL_IMMEDIATE_FUNCTION_P for consteval.
(grokdeclarator): Handle consteval.  Use %qs with keyword strings to
simplify translation.  Use separate ifs instead of chained else if
for invalid specifiers.  For constinit clear constinit_p rather than
constexpr_p.
* constexpr.c (find_immediate_fndecl): New function.
(cxx_eval_outermost_constant_expr): Allow consteval calls returning
void.  Diagnose returning address of immediate function from consteval
evaluation.
(fold_non_dependent_expr_template): Add OBJECT argument, pass it
through to cxx_eval_outermost_constant_expr.
(fold_non_dependent_expr): Add OBJECT argument, pass it through to
fold_non_dependent_expr_template.
(fold_non_dependent_init): Adjust fold_non_dependent_expr_template
caller.
* method.c (defaulted_late_check): Adjust diagnostics for consteval.
* lambda.c 

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

2019-10-31 Thread Jakub Jelinek
On Wed, Oct 30, 2019 at 05:06:00PM -0400, Jason Merrill wrote:
> build_cplus_new does the magic of replacing a dummy argument, e.g.
> 
> >   if (obj_arg && is_dummy_object (obj_arg))
> > {
> >   call = build_cplus_new (DECL_CONTEXT (fndecl), call, 
> > complain);
> >   obj_arg = NULL_TREE;
> > }
> 
> And then if the return value from build_special_member_call is
> TREE_CONSTANT, we can return that directly from build_value_init rather than
> look for an AGGR_INIT_EXPR.

Ok, that works.

> Hmm, it shouldn't be hard to scan ahead to see if there's a consteval after
> the parameter list.

Done it that way, we already have all the needed skip routines so nothing
really needs to be parsed, just skipped.

I've added some further tests and run into another issue, that for const
or constexpr vars with consteval ctor constexpr evaluation complained that
the ctor can't modify non-static data members in the object.  The problem
was that obj_arg passed in that case was *(S *) where var had const S
type, so had to add code to pass var in that case.

Bootstrapped/regtested on x86_64-linux and i686-linux, all tests pass now,
ok for trunk?

2019-10-31  Jakub Jelinek  

PR c++/88335 - Implement P1073R3: Immediate functions
c-family/
* c-common.h (enum rid): Add RID_CONSTEVAL.
* c-common.c (c_common_reswords): Add consteval.
cp/
* cp-tree.h (struct lang_decl_fn): Add immediate_fn_p bit.
(DECL_IMMEDIATE_FUNCTION_P, SET_DECL_IMMEDIATE_FUNCTION_P): Define.
(enum cp_decl_spec): Add ds_consteval.
(fold_non_dependent_expr): Add another tree argument defaulted to
NULL_TREE.
* name-lookup.h (struct cp_binding_level): Add immediate_fn_ctx_p
member.
* parser.c (cp_keyword_starts_decl_specifier_p): Adjust comments
for C++11 and C++20 specifiers.  Handle RID_CONSTEVAL.
(CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR): Adjust comment.
(CP_PARSER_FLAGS_CONSTEVAL): New.
(cp_parser_skip_balanced_tokens): New forward declaration.
(cp_parser_lambda_declarator_opt): Handle ds_consteval.  Set
current_binding_level->immediate_fn_ctx_p before parsing parameter
list if decl-specifier-seq contains consteval specifier.
(cp_parser_decl_specifier_seq): Handle RID_CONSTEVAL.
(cp_parser_explicit_instantiation): Diagnose explicit instantiation
with consteval specifier.
(cp_parser_init_declarator): For consteval or into flags
CP_PARSER_FLAGS_CONSTEVAL.
(cp_parser_direct_declarator): If CP_PARSER_FLAGS_CONSTEVAL, set
current_binding_level->immediate_fn_ctx_p in the sk_function_parms
scope.
(set_and_check_decl_spec_loc): Add consteval entry, formatting fix.
* call.c (build_addr_func): For direct calls to immediate functions
use build_address rather than decay_conversion.
(build_over_call): Evaluate immediate function invocations.
* error.c (dump_function_decl): Handle DECL_IMMEDIATE_FUNCTION_P.
* semantics.c (expand_or_defer_fn_1): Use tentative linkage and don't
call mark_needed for immediate functions.
* typeck.c (cxx_sizeof_or_alignof_expr): Likewise.  Formatting fix.
(cp_build_addr_expr_1): Reject taking address of immediate function
outside of immediate function.
* decl.c (validate_constexpr_redeclaration): Diagnose consteval
vs. non-consteval or vice versa redeclaration.  Use
SET_DECL_IMMEDIATE_FUNCTION_P if new_decl is immediate function.
(check_tag_decl): Use %qs with keyword string to simplify translation.
Handle ds_consteval.
(start_decl): Adjust diagnostics for static or thread_local variables
in immediate functions.
(grokfndecl): Call sorry_at on virtual consteval.  Use %qs with keyword
to string to simplify translation.  Diagnose consteval main.  Use
SET_DECL_IMMEDIATE_FUNCTION_P for consteval.
(grokdeclarator): Handle consteval.  Use %qs with keyword strings to
simplify translation.  Use separate ifs instead of chained else if
for invalid specifiers.  For constinit clear constinit_p rather than
constexpr_p.
* constexpr.c (find_immediate_fndecl): New function.
(cxx_eval_outermost_constant_expr): Allow consteval calls returning
void.  Diagnose returning address of immediate function from consteval
evaluation.
(fold_non_dependent_expr_template): Add OBJECT argument, pass it
through to cxx_eval_outermost_constant_expr.
(fold_non_dependent_expr): Add OBJECT argument, pass it through to
fold_non_dependent_expr_template.
(fold_non_dependent_init): Adjust fold_non_dependent_expr_template
caller.
* method.c (defaulted_late_check): Adjust diagnostics for consteval.
* lambda.c (maybe_add_lambda_conv_op): Copy over
  

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

2019-10-30 Thread Jason Merrill

On 10/24/19 7:47 AM, Jakub Jelinek 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.


I've tried this approach, but am running into issues:
1) the normal constructors aren't an issue, all I was missing is passing
the object argument down to cxx_constant_value.  The only problem
(I'm aware of) is then the case where build_over_call is called on
a constructor on is_dummy_object, because that obviously isn't
usable in constant expression as something to store into.  This is
used e.g. in the value initialization in consteval8.C test, but probably
for vec init too and other cases.  I've tried to create a temporary in
that case, but consteval8.C still ICEs
/usr/src/gcc/gcc/testsuite/g++.dg/cpp2a/consteval8.C: In function 'int foo()':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp2a/consteval8.C:13:13: internal compiler 
error: tree check: expected aggr_init_expr, have target_expr in build
_value_init, at cp/init.c:372
0x190aa02 tree_check_failed(tree_node const*, char const*, int, char const*, 
...)
 ../../gcc/tree.c:9925
0x8c37d8 tree_check(tree_node*, char const*, int, char const*, tree_code)
 ../../gcc/tree.h:3267
0xa254b5 build_value_init(tree_node*, int)
 ../../gcc/cp/init.c:372


build_cplus_new does the magic of replacing a dummy argument, e.g.


  if (obj_arg && is_dummy_object (obj_arg))
{
  call = build_cplus_new (DECL_CONTEXT (fndecl), call, complain);
  obj_arg = NULL_TREE;
}


And then if the return value from build_special_member_call is 
TREE_CONSTANT, we can return that directly from build_value_init rather 
than look for an AGGR_INIT_EXPR.



2) all other testcases in the testsuite pass, but I'm worried about
default arguments in consteval lambdas.
consteval int bar () { return 42; }
consteval int baz () { return 1; }
typedef int (*fnptr) ();
consteval fnptr quux () { return bar; }

void
foo ()
{
   auto qux = [] (fnptr a = quux ()) consteval { return a (); };
   constexpr auto c = qux (baz);
   constexpr auto d = qux (bar);
   constexpr auto e = qux ();
   static_assert (c == 1);
   static_assert (d == 42);
   static_assert (e == 42);
}
   I believe qux (baz) and qux (bar) are invalid and the patch rejects
   it (I think innermost non-block scope for the baz in qux (baz) is
   not a function parameter scope of an immediate function and so taking
   the address there is invalid.  But isn't the qux () call ok?
   I mean it is similar to the non-lambda calls in the example in the
   standard.  Unfortunately, when parsing the default arguments of a
   lambda, we haven't seen the consteval keyword yet.  I think we could
   tentatively set the consteval argument scope when parsing any lambda
   and if it is not consteval, call a cxx_eval_consteval like function
   to evaluate it at that point.  Thoughts on that?


Hmm, it shouldn't be hard to scan ahead to see if there's a consteval 
after the parameter list.


On the other hand, your suggestion also sounds reasonable, and if we do 
that for lambdas, we could do it for all functions instead of messing 
with the binding level.


Up to you.


3) compared to the May version of the patch, I also found that
build_over_call has a completely separate path if
processing_template_decl and does something much simpler in that
case, but I believe we still need to evaluate consteval calls
even if processing_template_decl if they aren't dependent.


I think such calls fall under the rule that if no valid instantiation is 
possible, the function is ill-formed, no diagnostic required.


So it's desirable, but not necessary.


2019-10-24  Jakub Jelinek  

PR c++/88335 - Implement P1073R3: Immediate functions
c-family/
* c-common.h (enum rid): Add RID_CONSTEVAL.
* c-common.c (c_common_reswords): Add consteval.
cp/
* cp-tree.h (struct lang_decl_fn): Add immediate_fn_p bit.
(DECL_IMMEDIATE_FUNCTION_P, SET_DECL_IMMEDIATE_FUNCTION_P): Define.
(enum cp_decl_spec): Add ds_consteval.
(build_local_temp): Declare.
(fold_non_dependent_expr): Add another tree argument defaulted to
NULL_TREE.
* name-lookup.h (struct cp_binding_level): Add immediate_fn_ctx_p
member.
* tree.c (build_local_temp): Remove forward declaration, no longer
static.
* parser.c (cp_keyword_starts_decl_specifier_p): Adjust comments
for C++11 and C++20 specifiers.  Handle RID_CONSTEVAL.
(CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR): Adjust comment.
(CP_PARSER_FLAGS_CONSTEVAL): New.
(cp_parser_lambda_declarator_opt): Handle ds_consteval.
(cp_parser_decl_specifier_seq): Handle RID_CONSTEVAL.
(cp_parser_explicit_instantiation): Diagnose explicit instantiation
with consteval specifier.

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

2019-10-24 Thread Jakub Jelinek
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.

I've tried this approach, but am running into issues:
1) the normal constructors aren't an issue, all I was missing is passing
   the object argument down to cxx_constant_value.  The only problem
   (I'm aware of) is then the case where build_over_call is called on
   a constructor on is_dummy_object, because that obviously isn't
   usable in constant expression as something to store into.  This is
   used e.g. in the value initialization in consteval8.C test, but probably
   for vec init too and other cases.  I've tried to create a temporary in
   that case, but consteval8.C still ICEs
/usr/src/gcc/gcc/testsuite/g++.dg/cpp2a/consteval8.C: In function 'int foo()':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp2a/consteval8.C:13:13: internal compiler 
error: tree check: expected aggr_init_expr, have target_expr in build
_value_init, at cp/init.c:372
0x190aa02 tree_check_failed(tree_node const*, char const*, int, char const*, 
...)
../../gcc/tree.c:9925
0x8c37d8 tree_check(tree_node*, char const*, int, char const*, tree_code)
../../gcc/tree.h:3267
0xa254b5 build_value_init(tree_node*, int)
../../gcc/cp/init.c:372
2) all other testcases in the testsuite pass, but I'm worried about
   default arguments in consteval lambdas.
consteval int bar () { return 42; }
consteval int baz () { return 1; }
typedef int (*fnptr) ();
consteval fnptr quux () { return bar; }

void
foo ()
{
  auto qux = [] (fnptr a = quux ()) consteval { return a (); };
  constexpr auto c = qux (baz);
  constexpr auto d = qux (bar);
  constexpr auto e = qux ();
  static_assert (c == 1);
  static_assert (d == 42);
  static_assert (e == 42);
}
  I believe qux (baz) and qux (bar) are invalid and the patch rejects
  it (I think innermost non-block scope for the baz in qux (baz) is
  not a function parameter scope of an immediate function and so taking
  the address there is invalid.  But isn't the qux () call ok?
  I mean it is similar to the non-lambda calls in the example in the
  standard.  Unfortunately, when parsing the default arguments of a
  lambda, we haven't seen the consteval keyword yet.  I think we could
  tentatively set the consteval argument scope when parsing any lambda
  and if it is not consteval, call a cxx_eval_consteval like function
  to evaluate it at that point.  Thoughts on that?

3) compared to the May version of the patch, I also found that
   build_over_call has a completely separate path if
   processing_template_decl and does something much simpler in that
   case, but I believe we still need to evaluate consteval calls
   even if processing_template_decl if they aren't dependent.

2019-10-24  Jakub Jelinek  

PR c++/88335 - Implement P1073R3: Immediate functions
c-family/
* c-common.h (enum rid): Add RID_CONSTEVAL.
* c-common.c (c_common_reswords): Add consteval.
cp/
* cp-tree.h (struct lang_decl_fn): Add immediate_fn_p bit.
(DECL_IMMEDIATE_FUNCTION_P, SET_DECL_IMMEDIATE_FUNCTION_P): Define.
(enum cp_decl_spec): Add ds_consteval.
(build_local_temp): Declare.
(fold_non_dependent_expr): Add another tree argument defaulted to
NULL_TREE.
* name-lookup.h (struct cp_binding_level): Add immediate_fn_ctx_p
member.
* tree.c (build_local_temp): Remove forward declaration, no longer
static.
* parser.c (cp_keyword_starts_decl_specifier_p): Adjust comments
for C++11 and C++20 specifiers.  Handle RID_CONSTEVAL.
(CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR): Adjust comment.
(CP_PARSER_FLAGS_CONSTEVAL): New.
(cp_parser_lambda_declarator_opt): Handle ds_consteval.
(cp_parser_decl_specifier_seq): Handle RID_CONSTEVAL.
(cp_parser_explicit_instantiation): Diagnose explicit instantiation
with consteval specifier.
(cp_parser_init_declarator): For consteval or into flags
CP_PARSER_FLAGS_CONSTEVAL.
(cp_parser_direct_declarator): If CP_PARSER_FLAGS_CONSTEVAL, set
current_binding_level->immediate_fn_ctx_p in the sk_function_parms
scope.
(set_and_check_decl_spec_loc): Add consteval entry, formatting fix.
* call.c (build_addr_func): For direct calls to immediate functions
use build_address rather than decay_conversion.
(build_over_call): Evaluate immediate function invocations.
* error.c (dump_function_decl): Handle DECL_IMMEDIATE_FUNCTION_P.
* semantics.c (expand_or_defer_fn_1): Use tentative linkage and don't
call mark_needed for immediate functions.
* typeck.c (cxx_sizeof_or_alignof_expr): Likewise.  Formatting fix.
(cp_build_addr_expr_1): Reject taking address of immediate function
outside of immediate function.
* decl.c (validate_constexpr_redeclaration): Diagnose 

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

2019-10-22 Thread Jason Merrill
On Tue, Oct 22, 2019 at 11:20 AM Jakub Jelinek  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


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

2019-10-22 Thread Jakub Jelinek
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 
> > 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



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

2019-10-22 Thread Jason Merrill
On Tue, Oct 22, 2019 at 10:41 AM Jakub Jelinek  wrote:
>
> On Tue, Oct 22, 2019 at 09:55:06AM -0400, Jason Merrill wrote:
> > On Mon, Oct 21, 2019 at 1:59 PM Jason Merrill  wrote:
> > > On 10/15/19 1:04 PM, Jakub Jelinek wrote:
> >
> > > > Unlike the previous implementation, this doesn't invoke consteval 
> > > > function
> > > > already during parsing, but later on, so there aren't issues with say
> > > > consteval constructors or consteval in default arguments.
> > >
> > > Right, we can't immediately evaluate a class prvalue before we know what
> > > object it's initializing.
> >
> > Actually, I'm not sure about this.  There's no way to consistently
> > know what object is being initialized soon enough for the evaluation
> > to be immediate, so I think we need to always create a temporary for
> > immediate invocations of class type, so we could go ahead and do
> > immediate evaluation in build_cxx_call.  I think this also follows
> > from an immediate invocation being a full-expression.
>
> So, do you prefer to do it the other way during build_cxx_call?

It seems more straightforward.

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

> How would I create a temporary into which construct the var?

The build_cplus_new in build_cxx_call creates a TARGET_EXPR,
evaluating that should be sufficient.  Note that you'll need to change
the condition there so that the decltype semantics don't apply to
immediate functions.

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

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

Jason


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

2019-10-22 Thread Jakub Jelinek
On Tue, Oct 22, 2019 at 09:55:06AM -0400, Jason Merrill wrote:
> On Mon, Oct 21, 2019 at 1:59 PM Jason Merrill  wrote:
> > On 10/15/19 1:04 PM, Jakub Jelinek wrote:
> 
> > > Unlike the previous implementation, this doesn't invoke consteval function
> > > already during parsing, but later on, so there aren't issues with say
> > > consteval constructors or consteval in default arguments.
> >
> > Right, we can't immediately evaluate a class prvalue before we know what
> > object it's initializing.
> 
> Actually, I'm not sure about this.  There's no way to consistently
> know what object is being initialized soon enough for the evaluation
> to be immediate, so I think we need to always create a temporary for
> immediate invocations of class type, so we could go ahead and do
> immediate evaluation in build_cxx_call.  I think this also follows
> from an immediate invocation being a full-expression.

So, do you prefer to do it the other way during build_cxx_call?

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?

How would I create a temporary into which construct the var?
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?

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 
void
foo ()
{
  if constexpr (foo (2))
{
  if constexpr (foo (1))
;
}
}
so, shouldn't immediate functions be called too?

Jakub



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

2019-10-22 Thread Jakub Jelinek
On Tue, Oct 22, 2019 at 09:52:44AM -0400, Jason Merrill wrote:
> Sounds good.
> 
> > (the latter perhaps just if !processing_template_decl)?
> 
> I'd think we would want to be consistent with other immediate
> invocations in template context.

The other ones just call it regardless of processing_template_decl.
The reason for !processing_template_decl would be that otherwise
tsubst_requires_expr calls finish_requires_expr which would already call the
finish_unevaluated_operand.  Though, I'm afraid it is unclear to me
where to call finish_unevaluated_operand in tsubst_requires_expr,
as we need to call it on a tsubsted expression (it was already called
on the non-tsubsted one), but it looks like tsubst_requirement_body
returns error_mark_node both in cases where there is some substitution
failure diagnosed, or when there is some failure.  And we don't call
tsubst_requirement_body at all if tsubst_constraint_variables fails.

> > In fact, the above with TREE_STATIC isn't enough, because
> > we perform cp_fold on non-TREE_STATIC initializers
> 
> Is that a problem?

If we cxx_eval_consteval first, then it isn't a problem I guess at least
for the consteval stuff.  Though, e.g. the initializer could contain
in constexpr functions expressions that during constexpr evaluation would
need to be diagnosed and cp_fold would make that go away.  Say out of bounds
access to something that cp_fold happily folds away.

> > Now, I'm afraid I have no idea what is the right behavior if immediate
> > invocations appear in discarded statements.  Guess we need testsuite
> > coverage for that too.
> 
> Discarded statements aren't instantiated at all, so we shouldn't see
> immediate invocations there.

Ok.

Jakub



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

2019-10-22 Thread Jason Merrill
On Mon, Oct 21, 2019 at 1:59 PM Jason Merrill  wrote:
> On 10/15/19 1:04 PM, Jakub Jelinek wrote:

> > Unlike the previous implementation, this doesn't invoke consteval function
> > already during parsing, but later on, so there aren't issues with say
> > consteval constructors or consteval in default arguments.
>
> Right, we can't immediately evaluate a class prvalue before we know what
> object it's initializing.

Actually, I'm not sure about this.  There's no way to consistently
know what object is being initialized soon enough for the evaluation
to be immediate, so I think we need to always create a temporary for
immediate invocations of class type, so we could go ahead and do
immediate evaluation in build_cxx_call.  I think this also follows
from an immediate invocation being a full-expression.

Jason


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

2019-10-22 Thread Jason Merrill
On Tue, Oct 22, 2019 at 3:15 AM Jakub Jelinek  wrote:
>
> On Mon, Oct 21, 2019 at 04:44:22PM -0400, Jason Merrill wrote:
> > Perhaps we should bypass the existing virtual function call mechanism for
> > consteval, and instead find the complete object directly and call
> > non-virtually.
>
> Maybe, but can that be done incrementally?

Certainly.

> > > The finish_function was just an attempt to limit the number of places 
> > > where
> > > we need to call it to a minimum.
> >
> > Fair enough.  Maybe just a finish_unevaluated_operand then.
>
> Good idea, added.
>
> Apparently there is one unevaluated operand I've missed, requires
> expression, but I don't know anything about concepts.  Do we need to call
> finish_unevaluated_operand from finish_requires_expr and tsubst_requires_expr

Sounds good.

> (the latter perhaps just if !processing_template_decl)?

I'd think we would want to be consistent with other immediate
invocations in template context.

> Are the requires params to be treated as non-constexpr entities (so e.g. 
> passing them to a
> consteval function would be an error)?

That's an open question, but let's assume so for now.

> > > +  if (init && TREE_STATIC (decl))
> > > +init = cxx_eval_consteval (init);
> >
> > Do we need this in addition to the cxx_constant_init in store_init_value?
>
> cxx_constant_init indeed can handle immediate invocations when it encounters
> them while evaluating the constant expression, like maybe_constant_value
> etc.  cxx_constant_init is not called on all initializers though,
> maybe_constant_value is called on others, and my understanding of consteval
> is that immediate invocations need to be evaluated anywhere in the
> expressions, not just in the subexpressions encountered during constexpr
> evaluation.

Good point.

> In fact, the above with TREE_STATIC isn't enough, because
> we perform cp_fold on non-TREE_STATIC initializers

Is that a problem?

> (maybe we shouldn't and defer that to cp_fold_function?)

I think it's done early now for the sake of constant evaluation later
in the function, but perhaps that's not necessary anymore.

> it is needed also for non-TREE_STATIC
> initializers, but even for TREE_STATIC, the first point is avoid evaluating
> immediate invocations multiple times and second ensure they are evaluated
> everywhere.  The way cxx_eval_consteval is written, it doesn't hurt if
> it is called multiple times, because it replaces the immediate evaluations
> with their constant values or void/zero constant (if errors were detected).
>
> I've added a whole new testcase (consteval11.C) which covers
> in 0 ? immediate_invocation : ... etc. and made the check_initializer
> changes that were needed for that.  Am not 100% sure about the
> diagnostics in consteval function when it is initializer of a constexpr
> function, but I believe in that case it isn't treated as immediate
> invocation, just normal call during constexpr processing.

> Now, I'm afraid I have no idea what is the right behavior if immediate
> invocations appear in discarded statements.  Guess we need testsuite
> coverage for that too.

Discarded statements aren't instantiated at all, so we shouldn't see
immediate invocations there.

Jason


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

2019-10-22 Thread Jakub Jelinek
On Mon, Oct 21, 2019 at 04:44:22PM -0400, Jason Merrill wrote:
> Perhaps we should bypass the existing virtual function call mechanism for
> consteval, and instead find the complete object directly and call
> non-virtually.

Maybe, but can that be done incrementally?

> > The finish_function was just an attempt to limit the number of places where
> > we need to call it to a minimum.
> 
> Fair enough.  Maybe just a finish_unevaluated_operand then.

Good idea, added.

Apparently there is one unevaluated operand I've missed, requires
expression, but I don't know anything about concepts.  Do we need to call
finish_unevaluated_operand from finish_requires_expr and tsubst_requires_expr
(the latter perhaps just if !processing_template_decl)?  Are the requires
params to be treated as non-constexpr entities (so e.g. passing them to a
consteval function would be an error)?

> > +  if (init && TREE_STATIC (decl))
> > +init = cxx_eval_consteval (init);
> 
> Do we need this in addition to the cxx_constant_init in store_init_value?

cxx_constant_init indeed can handle immediate invocations when it encounters
them while evaluating the constant expression, like maybe_constant_value
etc.  cxx_constant_init is not called on all initializers though,
maybe_constant_value is called on others, and my understanding of consteval
is that immediate invocations need to be evaluated anywhere in the
expressions, not just in the subexpressions encountered during constexpr
evaluation.  In fact, the above with TREE_STATIC isn't enough, because
we perform cp_fold on non-TREE_STATIC initializers (maybe we shouldn't and
defer that to cp_fold_function?), it is needed also for non-TREE_STATIC
initializers, but even for TREE_STATIC, the first point is avoid evaluating
immediate invocations multiple times and second ensure they are evaluated
everywhere.  The waqy cxx_eval_consteval is written, it doesn't hurt if
it is called multiple times, because it replaces the immediate evaluations
with their constant values or void/zero constant (if errors were detected).

I've added a whole new testcase (consteval11.C) which covers
in 0 ? immediate_invocation : ... etc. and made the check_initializer
changes that were needed for that.  Am not 100% sure about the
diagnostics in consteval function when it is initializer of a constexpr
function, but I believe in that case it isn't treated as immediate
invocation, just normal call during constexpr processing.

Now, I'm afraid I have no idea what is the right behavior if immediate
invocations appear in discarded statements.  Guess we need testsuite
coverage for that too.

Here is the updated patch.

2019-10-22  Jakub Jelinek  

PR c++/88335 - Implement P1073R3: Immediate functions
c-family/
* c-common.h (enum rid): Add RID_CONSTEVAL.
* c-common.c (c_common_reswords): Add consteval.
cp/
* cp-tree.h (struct lang_decl_fn): Add immediate_fn_p bit.
(DECL_IMMEDIATE_FUNCTION_P, SET_DECL_IMMEDIATE_FUNCTION_P): Define.
(enum cp_decl_spec): Add ds_consteval.
(cxx_eval_consteval, finish_unevaluated_operand): Declare.
* parser.c (cp_keyword_starts_decl_specifier_p): Adjust comments
for C++11 and C++20 specifiers.  Handle RID_CONSTEVAL.
(CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR): Adjust comment.
(cp_parser_has_attribute_expression): Call finish_unevaluated_operand.
(cp_parser_lambda_declarator_opt): Handle ds_consteval.
(cp_parser_decl_specifier_seq): Handle RID_CONSTEVAL.
(cp_parser_explicit_instantiation): Diagnose explicit instantiation
with consteval specifier.
(set_and_check_decl_spec_loc): Add consteval entry, formatting fix.
* call.c (build_addr_func): For direct calls to immediate functions
use build_address rather than decay_conversion.
* error.c (dump_function_decl): Handle DECL_IMMEDIATE_FUNCTION_P.
* semantics.c (expand_or_defer_fn_1): Use tentative linkage and don't
call mark_needed for immediate functions.
(finish_decltype_type): Call finish_unevaluated_operand.
* typeck.c (cxx_sizeof_or_alignof_expr): Likewise.  Formatting fix.
(cp_build_addr_expr_1): Reject taking address of immediate function
outside of immediate function.
* decl.c (validate_constexpr_redeclaration): Diagnose consteval
vs. non-consteval or vice versa redeclaration.  Use
SET_DECL_IMMEDIATE_FUNCTION_P if new_decl is immediate function.
(check_tag_decl): Use %qs with keyword string to simplify translation.
Handle ds_consteval.
(start_decl): Adjust diagnostics for static or thread_local variables
in immediate functions.
(check_initializer): Call cxx_eval_consteval.
(grokfndecl): Call sorry_at on virtual consteval.  Use %qs with keyword
to string to simplify translation.  Diagnose consteval main.  Use
SET_DECL_IMMEDIATE_FUNCTION_P for consteval.

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

2019-10-21 Thread Jason Merrill

On 10/21/19 2:49 PM, Jakub Jelinek wrote:

On Mon, Oct 21, 2019 at 01:59:38PM -0400, Jason Merrill wrote:

I agree that cp_fold isn't the right place, since it does lowering for GCC
internals, and consteval expansion is part of the language semantics.  So it
should happen before constexpr body saving, as in your patch.

It seems like we want a finish_full_expression, and do consteval folding
there (and not from finish_function).


The finish_function was just an attempt to limit the number of places where
we need to call it to a minimum.


Fair enough.  Maybe just a finish_unevaluated_operand then.


+  if (init && TREE_STATIC (decl))
+init = cxx_eval_consteval (init);


Do we need this in addition to the cxx_constant_init in store_init_value?

Jason


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

2019-10-21 Thread Jakub Jelinek
On Mon, Oct 21, 2019 at 01:59:38PM -0400, Jason Merrill wrote:
> I agree that cp_fold isn't the right place, since it does lowering for GCC
> internals, and consteval expansion is part of the language semantics.  So it
> should happen before constexpr body saving, as in your patch.
> 
> It seems like we want a finish_full_expression, and do consteval folding
> there (and not from finish_function).

Do we have a reasonable place to catch the full expressions?

I mean, perhaps add_stmt if stmts_are_full_exprs_p () and the spots where
unevaluated operands are handled in the patch, but an immediate invocation
is also a full-expression but for the default argument expressions we don't
know if the calls will be immediate invocation or not. 
Aren't there hundreds of other places where full expressions are handled
though?  I mean, e.g. all expressions in OpenMP/OpenACC clauses, etc.?
If the consteval evaluation is performed from this finish_full_expression,
we'd also need to *walk_subtrees = 0; if we encounter already handled full
expressions in there (e.g. statement expressions etc.).

The finish_function was just an attempt to limit the number of places where
we need to call it to a minimum.

Jakub



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

2019-10-21 Thread Jason Merrill

On 10/15/19 1:04 PM, Jakub Jelinek wrote:

Hi!

The following patch implements P1073R3, i.e. consteval, except that
virtual consteval is not supported (I think support for that would need to
include the consteval virtual methods at the end of the binfo structures
after all non-consteval virtual methods, but make sure we don't actually
emit those in the actual virtual tables etc.).


Perhaps we should bypass the existing virtual function call mechanism 
for consteval, and instead find the complete object directly and call 
non-virtually.



Unlike the previous implementation, this doesn't invoke consteval function
already during parsing, but later on, so there aren't issues with say
consteval constructors or consteval in default arguments.


Right, we can't immediately evaluate a class prvalue before we know what 
object it's initializing.



Initially I thought the best spot to do that would be during cp_fold, but
that isn't called e.g. on template function bodies before instantiation,
or on the expressions from unevaluated contexts, so I had to add a function
to walk trees and evaluate consteval function calls found in there.
Furthermore, cp_fold isn't called just during cp_fold_function, but also
during fold_for_warn etc., so some consteval functions might be evaluated
multiple times, which can be a problem that if there are errors, they might
be emitted multiple times.


I agree that cp_fold isn't the right place, since it does lowering for 
GCC internals, and consteval expansion is part of the language 
semantics.  So it should happen before constexpr body saving, as in your 
patch.


It seems like we want a finish_full_expression, and do consteval folding 
there (and not from finish_function).


Jason



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

2019-10-15 Thread Jakub Jelinek
Hi!

The following patch implements P1073R3, i.e. consteval, except that
virtual consteval is not supported (I think support for that would need to
include the consteval virtual methods at the end of the binfo structures
after all non-consteval virtual methods, but make sure we don't actually
emit those in the actual virtual tables etc.).

Unlike the previous implementation, this doesn't invoke consteval function
already during parsing, but later on, so there aren't issues with say
consteval constructors or consteval in default arguments.
Initially I thought the best spot to do that would be during cp_fold, but
that isn't called e.g. on template function bodies before instantiation,
or on the expressions from unevaluated contexts, so I had to add a function
to walk trees and evaluate consteval function calls found in there.
Furthermore, cp_fold isn't called just during cp_fold_function, but also
during fold_for_warn etc., so some consteval functions might be evaluated
multiple times, which can be a problem that if there are errors, they might
be emitted multiple times.

If you think it is worth avoiding the tree walk for -std=c++2a for the
finish_function of non-templates, perhaps it could be done during
cp_genericize too.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2019-10-15  Jakub Jelinek  

PR c++/88335 - Implement P1073R3: Immediate functions
c-family/
* c-common.h (enum rid): Add RID_CONSTEVAL.
* c-common.c (c_common_reswords): Add consteval.
cp/
* cp-tree.h (struct lang_decl_fn): Add immediate_fn_p bit.
(DECL_IMMEDIATE_FUNCTION_P, SET_DECL_IMMEDIATE_FUNCTION_P): Define.
(enum cp_decl_spec): Add ds_consteval.
(cxx_eval_consteval): Declare.
* parser.c (cp_keyword_starts_decl_specifier_p): Adjust comments
for C++11 and C++20 specifiers.  Handle RID_CONSTEVAL.
(CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR): Adjust comment.
(cp_parser_has_attribute_expression): Call cxx_eval_consteval.
(cp_parser_lambda_declarator_opt): Handle ds_consteval.
(cp_parser_decl_specifier_seq): Handle RID_CONSTEVAL.
(cp_parser_explicit_instantiation): Diagnose explicit instantiation
with consteval specifier.
(set_and_check_decl_spec_loc): Add consteval entry, formatting fix.
* call.c (build_addr_func): For direct calls to immediate functions
use build_address rather than decay_conversion.
* error.c (dump_function_decl): Handle DECL_IMMEDIATE_FUNCTION_P.
* semantics.c (expand_or_defer_fn_1): Use tentative linkage and don't
call mark_needed for immediate functions.
(finish_decltype_type): Call cxx_eval_consteval.
* typeck.c (cxx_sizeof_or_alignof_expr): Likewise.  Formatting fix.
(cp_build_addr_expr_1): Reject taking address of immediate function
outside of immediate function.
* decl.c (validate_constexpr_redeclaration): Diagnose consteval
vs. non-consteval or vice versa redeclaration.  Use
SET_DECL_IMMEDIATE_FUNCTION_P if new_decl is immediate function.
(check_tag_decl): Use %qs with keyword string to simplify translation.
Handle ds_consteval.
(start_decl): Adjust diagnostics for static or thread_local variables
in immediate functions.
(check_initializer): Call cxx_eval_consteval.
(grokfndecl): Call sorry_at on virtual consteval.  Use %qs with keyword
to string to simplify translation.  Diagnose consteval main.  Use
SET_DECL_IMMEDIATE_FUNCTION_P for consteval.
(grokdeclarator): Handle consteval.  Use %qs with keyword strings to
simplify translation.  Use separate ifs instead of chained else if
for invalid specifiers.  For constinit clear constinit_p rather than
constexpr_p.
(finish_function): Call cxx_eval_consteval for non-immediate functions.
* constexpr.c (struct constexpr_global_ctx): Add in_consteval field,
initialize it in the constructor.
(cxx_eval_call_expression): When encountering immediate function call
outside of in_consteval and outside of immediate function, call
cxx_constant_value.
(find_immediate_fndecl): New function.
(cxx_eval_outermost_constant_expr): Allow consteval calls returning
void.  Set global_ctx.in_consteval.  Diagnose returning address of
immediate function from in_consteval evaluation.
(fold_non_dependent_expr_template): Add forward declaration.  Add
allow_non_constant argument and pass it through to
cxx_eval_outermost_constant_expr.
(cxx_eval_consteval_r, cxx_eval_consteval): New functions.
(fold_non_dependent_expr, fold_non_dependent_init): Adjust
fold_non_dependent_expr_template callers.
* method.c (defaulted_late_check): Adjust diagnostics for consteval.
* except.c (finish_noexcept_expr): Call cxx_eval_consteval.