diff options
author | Jakub Jelinek <jakub@redhat.com> | 2019-11-02 00:28:20 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2019-11-02 00:28:20 +0100 |
commit | f968ef9b8df2bc2287e5e7e87299e5a2a44e8c94 (patch) | |
tree | 6aba8238b5260a14347acaa810dbae9579df6f8d /gcc/cp/parser.c | |
parent | 8412b939d1cf375c8e478e39a5ac9d7260e4c23c (diff) | |
download | gcc-f968ef9b8df2bc2287e5e7e87299e5a2a44e8c94.zip gcc-f968ef9b8df2bc2287e5e7e87299e5a2a44e8c94.tar.gz gcc-f968ef9b8df2bc2287e5e7e87299e5a2a44e8c94.tar.bz2 |
PR c++/88335 - Implement P1073R3: Immediate functions
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
DECL_DECLARED_CONSTEXPR_P and DECL_IMMEDIATE_FUNCTION_P bits from
callop to both artificial functions.
* init.c (build_value_init): Don't do further processing if
build_special_member_call returned a TREE_CONSTANT. Formatting fix.
testsuite/
* g++.dg/cpp2a/consteval1.C: New test.
* g++.dg/cpp2a/consteval2.C: New test.
* g++.dg/cpp2a/consteval3.C: New test.
* g++.dg/cpp2a/consteval4.C: New test.
* g++.dg/cpp2a/consteval5.C: New test.
* g++.dg/cpp2a/consteval6.C: New test.
* g++.dg/cpp2a/consteval7.C: New test.
* g++.dg/cpp2a/consteval8.C: New test.
* g++.dg/cpp2a/consteval9.C: New test.
* g++.dg/cpp2a/consteval10.C: New test.
* g++.dg/cpp2a/consteval11.C: New test.
* g++.dg/cpp2a/consteval12.C: New test.
* g++.dg/cpp2a/consteval13.C: New test.
* g++.dg/cpp2a/consteval14.C: New test.
* g++.dg/ext/consteval1.C: New test.
From-SVN: r277733
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index f1664e6..516c14b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -998,11 +998,13 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword) /* GNU extensions. */ case RID_ATTRIBUTE: case RID_TYPEOF: - /* C++0x extensions. */ + /* C++11 extensions. */ case RID_DECLTYPE: case RID_UNDERLYING_TYPE: case RID_CONSTEXPR: + /* C++20 extensions. */ case RID_CONSTINIT: + case RID_CONSTEVAL: return true; default: @@ -1807,12 +1809,15 @@ enum /* When parsing a decl-specifier-seq, only allow type-specifier or constexpr. */ CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR = 0x8, - /* When parsing a decl-specifier-seq, only allow mutable or constexpr. */ + /* When parsing a decl-specifier-seq, only allow mutable, constexpr or + for C++2A consteval. */ CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR = 0x10, /* When parsing a decl-specifier-seq, allow missing typename. */ CP_PARSER_FLAGS_TYPENAME_OPTIONAL = 0x20, /* When parsing of the noexcept-specifier should be delayed. */ - CP_PARSER_FLAGS_DELAY_NOEXCEPT = 0x40 + CP_PARSER_FLAGS_DELAY_NOEXCEPT = 0x40, + /* When parsing a consteval declarator. */ + CP_PARSER_FLAGS_CONSTEVAL = 0x80 }; /* This type is used for parameters and variables which hold @@ -2671,6 +2676,7 @@ static bool cp_parser_init_statement_p (cp_parser *); static bool cp_parser_skip_to_closing_square_bracket (cp_parser *); +static size_t cp_parser_skip_balanced_tokens (cp_parser *, size_t); // -------------------------------------------------------------------------- // // Unevaluated Operand Guard @@ -10903,11 +10909,31 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) opening parenthesis if present. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { + bool is_consteval = false; + /* For C++20, before parsing the parameter list check if there is + a consteval specifier in the corresponding decl-specifier-seq. */ + if (cxx_dialect >= cxx2a) + { + for (size_t n = cp_parser_skip_balanced_tokens (parser, 1); + cp_lexer_nth_token_is (parser->lexer, n, CPP_KEYWORD); n++) + { + if (cp_lexer_peek_nth_token (parser->lexer, n)->keyword + == RID_CONSTEVAL) + { + is_consteval = true; + break; + } + } + } + matching_parens parens; parens.consume_open (parser); begin_scope (sk_function_parms, /*entity=*/NULL_TREE); + if (is_consteval) + current_binding_level->immediate_fn_ctx_p = true; + /* Parse parameters. */ param_list = cp_parser_parameter_declaration_clause @@ -10992,6 +11018,9 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) "lambda only available with %<-std=c++17%> or " "%<-std=gnu++17%>"); } + if (lambda_specs.locations[ds_consteval]) + return_type_specs.locations[ds_consteval] + = lambda_specs.locations[ds_consteval]; p = obstack_alloc (&declarator_obstack, 0); @@ -14052,6 +14081,11 @@ cp_parser_decl_specifier_seq (cp_parser* parser, cp_lexer_consume_token (parser->lexer); break; + case RID_CONSTEVAL: + ds = ds_consteval; + cp_lexer_consume_token (parser->lexer); + break; + case RID_CONCEPT: ds = ds_concept; cp_lexer_consume_token (parser->lexer); @@ -14169,7 +14203,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser, if (found_decl_spec && (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR) && token->keyword != RID_MUTABLE - && token->keyword != RID_CONSTEXPR) + && token->keyword != RID_CONSTEXPR + && token->keyword != RID_CONSTEVAL) error_at (token->location, "%qD invalid in lambda", ridpointers[token->keyword]); @@ -17310,6 +17345,10 @@ cp_parser_explicit_instantiation (cp_parser* parser) permerror (decl_specifiers.locations[ds_constexpr], "explicit instantiation shall not use" " %<constexpr%> specifier"); + if (decl_spec_seq_has_spec_p (&decl_specifiers, ds_consteval)) + permerror (decl_specifiers.locations[ds_consteval], + "explicit instantiation shall not use" + " %<consteval%> specifier"); decl = grokdeclarator (declarator, &decl_specifiers, NORMAL, 0, &decl_specifiers.attributes); @@ -20295,6 +20334,9 @@ cp_parser_init_declarator (cp_parser* parser, bool saved_default_arg_ok_p = parser->default_arg_ok_p; location_t tmp_init_loc = UNKNOWN_LOCATION; + if (decl_spec_seq_has_spec_p (decl_specifiers, ds_consteval)) + flags |= CP_PARSER_FLAGS_CONSTEVAL; + /* Gather the attributes that were provided with the decl-specifiers. */ prefix_attributes = decl_specifiers->attributes; @@ -20939,6 +20981,10 @@ cp_parser_direct_declarator (cp_parser* parser, begin_scope (sk_function_parms, NULL_TREE); + /* Signal we are in the immediate function context. */ + if (flags & CP_PARSER_FLAGS_CONSTEVAL) + current_binding_level->immediate_fn_ctx_p = true; + /* Parse the parameter-declaration-clause. */ params = cp_parser_parameter_declaration_clause (parser, flags); @@ -29960,9 +30006,10 @@ set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs, "friend", "typedef", "using", - "constexpr", + "constexpr", "__complex", - "constinit" + "constinit", + "consteval" }; gcc_rich_location richloc (location); richloc.add_fixit_remove (); |