diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-09-16 09:11:19 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-09-16 09:11:19 +0000 |
commit | 2f7625017c3866c20a9d94fba926155f2c31e875 (patch) | |
tree | cae7430f04748a1dfbb6829f711a90c714fba92a /gcc/cp/parser.c | |
parent | e890a33c3b3bb2ec709d44c90c708acc38573322 (diff) | |
download | gcc-2f7625017c3866c20a9d94fba926155f2c31e875.tar.gz |
2013-09-16 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 202619 using svnmerge.py
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@202622 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 345 |
1 files changed, 287 insertions, 58 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 923277b6daa..2cd60f0db9d 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see #include "plugin.h" #include "tree-pretty-print.h" #include "parser.h" +#include "type-utils.h" /* The lexer. */ @@ -2063,6 +2064,11 @@ static vec<constructor_elt, va_gc> *cp_parser_initializer_list static bool cp_parser_ctor_initializer_opt_and_function_body (cp_parser *, bool); +static tree add_implicit_template_parms + (cp_parser *, size_t, tree); +static tree finish_fully_implicit_template + (cp_parser *, tree); + /* Classes [gram.class] */ static tree cp_parser_class_name @@ -3385,6 +3391,9 @@ cp_parser_new (void) /* No template parameters apply. */ parser->num_template_parameter_lists = 0; + /* Not declaring an implicit function template. */ + parser->fully_implicit_function_template_p = false; + return parser; } @@ -5533,6 +5542,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, cp_id_kind * pidk_return) { cp_token *token; + location_t loc; enum rid keyword; cp_id_kind idk = CP_ID_KIND_NONE; tree postfix_expression = NULL_TREE; @@ -5540,6 +5550,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); + loc = token->location; /* Some of the productions are determined by keywords. */ keyword = token->keyword; switch (keyword) @@ -5685,7 +5696,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, vec<tree, va_gc> *vec; unsigned int i; tree p; - location_t loc = token->location; cp_lexer_consume_token (parser->lexer); vec = cp_parser_parenthesized_expression_list (parser, non_attr, @@ -6018,8 +6028,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, postfix_expression = cp_parser_postfix_dot_deref_expression (parser, token->type, postfix_expression, - false, &idk, - token->location); + false, &idk, loc); is_member_access = true; break; @@ -6338,7 +6347,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, pseudo_destructor_p = true; postfix_expression = finish_pseudo_destructor_expr (postfix_expression, - s, type); + s, type, location); } } @@ -8549,10 +8558,12 @@ cp_parser_lambda_expression (cp_parser* parser) = parser->num_template_parameter_lists; unsigned char in_statement = parser->in_statement; bool in_switch_statement_p = parser->in_switch_statement_p; + bool fully_implicit_function_template_p = parser->fully_implicit_function_template_p; parser->num_template_parameter_lists = 0; parser->in_statement = 0; parser->in_switch_statement_p = false; + parser->fully_implicit_function_template_p = false; /* By virtue of defining a local class, a lambda expression has access to the private variables of enclosing classes. */ @@ -8576,6 +8587,7 @@ cp_parser_lambda_expression (cp_parser* parser) parser->num_template_parameter_lists = saved_num_template_parameter_lists; parser->in_statement = in_statement; parser->in_switch_statement_p = in_switch_statement_p; + parser->fully_implicit_function_template_p = fully_implicit_function_template_p; } pop_deferring_access_checks (); @@ -8753,6 +8765,14 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) /*template_arg_p=*/false, &error_msg, capture_token->location); + + if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) + { + cp_lexer_consume_token (parser->lexer); + capture_init_expr = make_pack_expansion (capture_init_expr); + } + else + check_for_bare_parameter_packs (capture_init_expr); } if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE @@ -8783,6 +8803,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) /* Parse the (optional) middle of a lambda expression. lambda-declarator: + < template-parameter-list [opt] > ( parameter-declaration-clause [opt] ) attribute-specifier [opt] mutable [opt] @@ -8802,9 +8823,30 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) tree param_list = void_list_node; tree attributes = NULL_TREE; tree exception_spec = NULL_TREE; + tree template_param_list = NULL_TREE; + + /* The template-parameter-list is optional, but must begin with + an opening angle if present. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) + { + if (cxx_dialect < cxx1y) + pedwarn (parser->lexer->next_token->location, 0, + "lambda templates are only available with " + "-std=c++1y or -std=gnu++1y"); + + cp_lexer_consume_token (parser->lexer); + + template_param_list = cp_parser_template_parameter_list (parser); + + cp_parser_skip_to_end_of_template_parameter_list (parser); + + /* We just processed one more parameter list. */ + ++parser->num_template_parameter_lists; + } - /* The lambda-declarator is optional, but must begin with an opening - parenthesis if present. */ + /* The parameter-declaration-clause is optional (unless + template-parameter-list was given), but must begin with an + opening parenthesis if present. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { cp_lexer_consume_token (parser->lexer); @@ -8847,6 +8889,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) trailing-return-type in case of decltype. */ pop_bindings_and_leave_scope (); } + else if (template_param_list != NULL_TREE) // generate diagnostic + cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); /* Create the function call operator. @@ -8890,6 +8934,14 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) DECL_ARTIFICIAL (fco) = 1; /* Give the object parameter a different name. */ DECL_NAME (DECL_ARGUMENTS (fco)) = get_identifier ("__closure"); + if (template_param_list) + { + fco = finish_member_template_decl (fco); + finish_template_decl (template_param_list); + --parser->num_template_parameter_lists; + } + else if (parser->fully_implicit_function_template_p) + fco = finish_fully_implicit_template (parser, fco); } finish_member_declaration (fco); @@ -9012,7 +9064,11 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) finish_lambda_scope (); /* Finish the function and generate code for it if necessary. */ - expand_or_defer_fn (finish_function (/*inline*/2)); + tree fn = finish_function (/*inline*/2); + + /* Only expand if the call op is not a template. */ + if (!DECL_TEMPLATE_INFO (fco)) + expand_or_defer_fn (fn); } parser->local_variables_forbidden_p = local_variables_forbidden_p; @@ -16247,56 +16303,62 @@ cp_parser_init_declarator (cp_parser* parser, /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); - /* Check to see if the token indicates the start of a - function-definition. */ - if (function_declarator_p (declarator) - && cp_parser_token_starts_function_definition_p (token)) + + if (function_declarator_p (declarator)) { - if (!function_definition_allowed_p) + /* Check to see if the token indicates the start of a + function-definition. */ + if (cp_parser_token_starts_function_definition_p (token)) { - /* If a function-definition should not appear here, issue an - error message. */ - cp_parser_error (parser, - "a function-definition is not allowed here"); - return error_mark_node; - } - else - { - location_t func_brace_location - = cp_lexer_peek_token (parser->lexer)->location; - - /* Neither attributes nor an asm-specification are allowed - on a function-definition. */ - if (asm_specification) - error_at (asm_spec_start_token->location, - "an asm-specification is not allowed " - "on a function-definition"); - if (attributes) - error_at (attributes_start_token->location, - "attributes are not allowed on a function-definition"); - /* This is a function-definition. */ - *function_definition_p = true; - - /* Parse the function definition. */ - if (member_p) - decl = cp_parser_save_member_function_body (parser, - decl_specifiers, - declarator, - prefix_attributes); - else - decl - = (cp_parser_function_definition_from_specifiers_and_declarator - (parser, decl_specifiers, prefix_attributes, declarator)); - - if (decl != error_mark_node && DECL_STRUCT_FUNCTION (decl)) + if (!function_definition_allowed_p) { - /* This is where the prologue starts... */ - DECL_STRUCT_FUNCTION (decl)->function_start_locus - = func_brace_location; + /* If a function-definition should not appear here, issue an + error message. */ + cp_parser_error (parser, + "a function-definition is not allowed here"); + return error_mark_node; } + else + { + location_t func_brace_location + = cp_lexer_peek_token (parser->lexer)->location; + + /* Neither attributes nor an asm-specification are allowed + on a function-definition. */ + if (asm_specification) + error_at (asm_spec_start_token->location, + "an asm-specification is not allowed " + "on a function-definition"); + if (attributes) + error_at (attributes_start_token->location, + "attributes are not allowed " + "on a function-definition"); + /* This is a function-definition. */ + *function_definition_p = true; + + /* Parse the function definition. */ + if (member_p) + decl = cp_parser_save_member_function_body (parser, + decl_specifiers, + declarator, + prefix_attributes); + else + decl = + (cp_parser_function_definition_from_specifiers_and_declarator + (parser, decl_specifiers, prefix_attributes, declarator)); - return decl; + if (decl != error_mark_node && DECL_STRUCT_FUNCTION (decl)) + { + /* This is where the prologue starts... */ + DECL_STRUCT_FUNCTION (decl)->function_start_locus + = func_brace_location; + } + + return decl; + } } + else if (parser->fully_implicit_function_template_p) + decl = finish_fully_implicit_template (parser, decl); } /* [dcl.dcl] @@ -16756,8 +16818,10 @@ cp_parser_direct_declarator (cp_parser* parser, /* Parse the parameter-declaration-clause. */ params = cp_parser_parameter_declaration_clause (parser); + /* Restore saved template parameter lists accounting for implicit + template parameters. */ parser->num_template_parameter_lists - = saved_num_template_parameter_lists; + += saved_num_template_parameter_lists; /* Consume the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); @@ -17855,6 +17919,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) tree *tail = ¶meters; bool saved_in_unbraced_linkage_specification_p; int index = 0; + int implicit_template_parms = 0; /* Assume all will go well. */ *is_error = false; @@ -17882,11 +17947,18 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) deprecated_state = DEPRECATED_SUPPRESS; if (parameter) - decl = grokdeclarator (parameter->declarator, - ¶meter->decl_specifiers, - PARM, - parameter->default_argument != NULL_TREE, - ¶meter->decl_specifiers.attributes); + { + decl = grokdeclarator (parameter->declarator, + ¶meter->decl_specifiers, + PARM, + parameter->default_argument != NULL_TREE, + ¶meter->decl_specifiers.attributes); + + if (TREE_TYPE (decl) != error_mark_node + && parameter->decl_specifiers.type + && is_auto_or_concept (parameter->decl_specifiers.type)) + ++implicit_template_parms; + } deprecated_state = DEPRECATED_NORMAL; @@ -17974,6 +18046,11 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) parser->in_unbraced_linkage_specification_p = saved_in_unbraced_linkage_specification_p; + if (parameters != error_mark_node && implicit_template_parms) + parameters = add_implicit_template_parms (parser, + implicit_template_parms, + parameters); + return parameters; } @@ -19980,7 +20057,11 @@ cp_parser_member_declaration (cp_parser* parser) attributes); /* If the member was not a friend, declare it here. */ if (!friend_p) - finish_member_declaration (decl); + { + if (parser->fully_implicit_function_template_p) + decl = finish_fully_implicit_template (parser, decl); + finish_member_declaration (decl); + } /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* If the next token is a semicolon, consume it. */ @@ -19996,6 +20077,8 @@ cp_parser_member_declaration (cp_parser* parser) initializer, /*init_const_expr_p=*/true, asm_specification, attributes); + if (parser->fully_implicit_function_template_p) + decl = finish_fully_implicit_template (parser, decl); } /* Reset PREFIX_ATTRIBUTES. */ @@ -22263,6 +22346,9 @@ cp_parser_function_definition_after_declarator (cp_parser* parser, = saved_num_template_parameter_lists; parser->in_function_body = saved_in_function_body; + if (parser->fully_implicit_function_template_p) + finish_fully_implicit_template (parser, /*member_decl_opt=*/0); + return fn; } @@ -28808,4 +28894,147 @@ c_parse_file (void) the_parser = NULL; } +/* Create an identifier for a generic parameter type (a synthesized + template parameter implied by `auto' or a concept identifier). */ + +static tree +make_generic_type_name (int i) +{ + char buf[32]; + sprintf (buf, "__GenT%d", i); + return get_identifier (buf); +} + +/* Predicate that behaves as is_auto_or_concept but matches the parent + node of the generic type rather than the generic type itself. This + allows for type transformation in add_implicit_template_parms. */ + +static inline bool +tree_type_is_auto_or_concept (const_tree t) +{ + return TREE_TYPE (t) && is_auto_or_concept (TREE_TYPE (t)); +} + +/* Add COUNT implicit template parameters gleaned from the generic + type parameters in PARAMETERS to the CURRENT_TEMPLATE_PARMS + (creating a new template parameter list if necessary). Returns + PARAMETERS suitably rewritten to reference the newly created types + or ERROR_MARK_NODE on failure. */ + +tree +add_implicit_template_parms (cp_parser *parser, size_t count, tree parameters) +{ + gcc_assert (current_binding_level->kind == sk_function_parms); + + cp_binding_level *fn_parms_scope = current_binding_level; + + bool become_template = + fn_parms_scope->level_chain->kind != sk_template_parms; + + size_t synth_idx = 0; + + /* Roll back a scope level and either introduce a new template parameter list + or update an existing one. The function scope is added back after template + parameter synthesis below. */ + current_binding_level = fn_parms_scope->level_chain; + + /* TPARMS tracks the function's template parameter list. This is either a new + chain in the case of a fully implicit function template or an extension of + the function's explicitly specified template parameter list. */ + tree tparms = NULL_TREE; + + if (become_template) + { + push_deferring_access_checks (dk_deferred); + begin_template_parm_list (); + + parser->fully_implicit_function_template_p = true; + ++parser->num_template_parameter_lists; + } + else + { + /* Roll back the innermost template parameter list such that it may be + extended in the loop below as if it were being explicitly declared. */ + + gcc_assert (current_template_parms); + + /* Pop the innermost template parms into TPARMS. */ + tree inner_vec = INNERMOST_TEMPLATE_PARMS (current_template_parms); + current_template_parms = TREE_CHAIN (current_template_parms); + + size_t inner_vec_len = TREE_VEC_LENGTH (inner_vec); + if (inner_vec_len != 0) + { + tree t = tparms = TREE_VEC_ELT (inner_vec, 0); + for (size_t n = 1; n < inner_vec_len; ++n) + t = TREE_CHAIN (t) = TREE_VEC_ELT (inner_vec, n); + } + + ++processing_template_parmlist; + } + + for (tree p = parameters; p && synth_idx < count; p = TREE_CHAIN (p)) + { + tree generic_type_ptr + = find_type_usage (TREE_VALUE (p), tree_type_is_auto_or_concept); + + if (!generic_type_ptr) + continue; + + tree synth_id = make_generic_type_name (synth_idx++); + tree synth_tmpl_parm = finish_template_type_parm (class_type_node, + synth_id); + tparms = process_template_parm (tparms, DECL_SOURCE_LOCATION (TREE_VALUE + (p)), + build_tree_list (NULL_TREE, + synth_tmpl_parm), + /*non_type=*/false, + /*param_pack=*/false); + + /* Rewrite the type of P to be the template_parm added above (getdecls is + used to retrieve it since it is the most recent declaration in this + scope). Qualifiers need to be preserved also. */ + + tree& cur_type = TREE_TYPE (generic_type_ptr); + tree new_type = TREE_TYPE (getdecls ()); + + if (TYPE_QUALS (cur_type)) + cur_type = cp_build_qualified_type (new_type, TYPE_QUALS (cur_type)); + else + cur_type = new_type; + } + + gcc_assert (synth_idx == count); + + push_binding_level (fn_parms_scope); + + end_template_parm_list (tparms); + + return parameters; +} + +/* Finish the declaration of a fully implicit function template. Such a + template has no explicit template parameter list so has not been through the + normal template head and tail processing. add_implicit_template_parms tries + to do the head; this tries to do the tail. MEMBER_DECL_OPT should be + provided if the declaration is a class member such that its template + declaration can be completed. If MEMBER_DECL_OPT is provided the finished + form is returned. Otherwise NULL_TREE is returned. */ + +tree +finish_fully_implicit_template (cp_parser *parser, tree member_decl_opt) +{ + gcc_assert (parser->fully_implicit_function_template_p); + + pop_deferring_access_checks (); + if (member_decl_opt) + member_decl_opt = finish_member_template_decl (member_decl_opt); + end_template_decl (); + + parser->fully_implicit_function_template_p = false; + --parser->num_template_parameter_lists; + + return member_decl_opt; +} + #include "gt-cp-parser.h" |