Re: [C++ PATCH] Implement P1073R3: Immediate functions (PR c++/88335, take 3)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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.