From 346e3a9c85f2878a54745f5065eb84eeeaed12f5 Mon Sep 17 00:00:00 2001 From: jason Date: Mon, 1 Sep 2008 03:33:19 +0000 Subject: [PATCH] Implement late-specified return type using 'auto'. * cp-tree.h (struct cp_declarator): Add late_return_type field to function declarator. * parser.c (cp_parser_late_return_type_opt): New fn. (cp_parser_direct_declarator): Use it. (make_call_declarator): Put it in the declarator. * decl.c (grokdeclarator): Splice in late-specified return type. * pt.c (splice_late_return_type): New fn. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@139848 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 11 +++++++++++ gcc/cp/cp-tree.h | 3 +++ gcc/cp/decl.c | 6 ++++++ gcc/cp/parser.c | 39 +++++++++++++++++++++++++++++++++++--- gcc/cp/pt.c | 17 +++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/auto6.C | 9 +++++++++ 6 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/auto6.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 30c6aa6..898beb0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2008-08-31 Jason Merrill + + Implement late-specified return type using 'auto'. + * cp-tree.h (struct cp_declarator): Add late_return_type field to + function declarator. + * parser.c (cp_parser_late_return_type_opt): New fn. + (cp_parser_direct_declarator): Use it. + (make_call_declarator): Put it in the declarator. + * decl.c (grokdeclarator): Splice in late-specified return type. + * pt.c (splice_late_return_type): New fn. + 2008-08-29 Michael Meissner * decl.c (builtin_function_1): Take a bool argument to decide diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 37bed91..a01d981 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4108,6 +4108,8 @@ struct cp_declarator { cp_cv_quals qualifiers; /* The exception-specification for the function. */ tree exception_specification; + /* The late-specified return type, if any. */ + tree late_return_type; } function; /* For arrays. */ struct { @@ -4525,6 +4527,7 @@ extern tree check_explicit_specialization (tree, tree, int, int); extern tree make_auto (void); extern tree do_auto_deduction (tree, tree, tree); extern tree type_uses_auto (tree); +extern tree splice_late_return_type (tree, tree); extern bool is_auto (const_tree); extern tree process_template_parm (tree, tree, bool, bool); extern tree end_template_parm_list (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 5a5a41f..0d735c4 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -8220,6 +8220,12 @@ grokdeclarator (const cp_declarator *declarator, /* Pick up the exception specifications. */ raises = declarator->u.function.exception_specification; + /* Handle a late-specified return type. */ + type = splice_late_return_type + (type, declarator->u.function.late_return_type); + if (type == error_mark_node) + return error_mark_node; + /* Say it's a definition only for the CALL_EXPR closest to the identifier. */ funcdecl_p = inner_declarator && inner_declarator->kind == cdk_id; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 08ec967..3d74d6c 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -853,7 +853,7 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs) VAR_DECLs or FUNCTION_DECLs) should do that directly. */ static cp_declarator *make_call_declarator - (cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree); + (cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree, tree); static cp_declarator *make_array_declarator (cp_declarator *, tree); static cp_declarator *make_pointer_declarator @@ -1015,7 +1015,8 @@ cp_declarator * make_call_declarator (cp_declarator *target, cp_parameter_declarator *parms, cp_cv_quals cv_qualifiers, - tree exception_specification) + tree exception_specification, + tree late_return_type) { cp_declarator *declarator; @@ -1024,6 +1025,7 @@ make_call_declarator (cp_declarator *target, declarator->u.function.parameters = parms; declarator->u.function.qualifiers = cv_qualifiers; declarator->u.function.exception_specification = exception_specification; + declarator->u.function.late_return_type = late_return_type; if (target) { declarator->parameter_pack_p = target->parameter_pack_p; @@ -1726,6 +1728,8 @@ static enum tree_code cp_parser_ptr_operator (cp_parser *, tree *, cp_cv_quals *); static cp_cv_quals cp_parser_cv_qualifier_seq_opt (cp_parser *); +static tree cp_parser_late_return_type_opt + (cp_parser *); static tree cp_parser_declarator_id (cp_parser *, bool); static tree cp_parser_type_id @@ -13021,6 +13025,7 @@ cp_parser_direct_declarator (cp_parser* parser, { cp_cv_quals cv_quals; tree exception_specification; + tree late_return; if (ctor_dtor_or_conv_p) *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0; @@ -13034,11 +13039,15 @@ cp_parser_direct_declarator (cp_parser* parser, exception_specification = cp_parser_exception_specification_opt (parser); + late_return + = cp_parser_late_return_type_opt (parser); + /* Create the function-declarator. */ declarator = make_call_declarator (declarator, params, cv_quals, - exception_specification); + exception_specification, + late_return); /* Any subsequent parameter lists are to do with return type, so are not those of the declared function. */ @@ -13516,6 +13525,30 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser) return cv_quals; } +/* Parse a late-specified return type, if any. This is not a separate + non-terminal, but part of a function declarator, which looks like + + -> type-id + + Returns the type indicated by the type-id. */ + +static tree +cp_parser_late_return_type_opt (cp_parser* parser) +{ + cp_token *token; + + /* Peek at the next token. */ + token = cp_lexer_peek_token (parser->lexer); + /* A late-specified return type is indicated by an initial '->'. */ + if (token->type != CPP_DEREF) + return NULL_TREE; + + /* Consume the ->. */ + cp_lexer_consume_token (parser->lexer); + + return cp_parser_type_id (parser); +} + /* Parse a declarator-id. declarator-id: diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5bb18d9..b05c7a0 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -16769,6 +16769,23 @@ do_auto_deduction (tree type, tree init, tree auto_node) return tsubst (type, targs, tf_warning_or_error, NULL_TREE); } +/* Substitutes LATE_RETURN_TYPE for 'auto' in TYPE and returns the + result. */ + +tree +splice_late_return_type (tree type, tree late_return_type) +{ + tree argvec; + + if (late_return_type == NULL_TREE) + return type; + argvec = make_tree_vec (1); + TREE_VEC_ELT (argvec, 0) = late_return_type; + if (processing_template_decl) + argvec = add_to_template_args (current_template_args (), argvec); + return tsubst (type, argvec, tf_warning_or_error, NULL_TREE); +} + /* Returns true iff TYPE is a TEMPLATE_TYPE_PARM representing 'auto'. */ bool diff --git a/gcc/testsuite/g++.dg/cpp0x/auto6.C b/gcc/testsuite/g++.dg/cpp0x/auto6.C new file mode 100644 index 0000000..ac20993 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/auto6.C @@ -0,0 +1,9 @@ +// { dg-options "-std=c++0x" } + +auto f() -> int +{ + return 0; +} + +template +auto add(T t, U u) -> decltype (t+u); // { dg-bogus "not declared" "" { xfail *-*-* } } -- 2.7.4