aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2008-08-31 23:33:19 -0400
committerJason Merrill <jason@gcc.gnu.org>2008-08-31 23:33:19 -0400
commitf57ca1ea5f9ebcd518961e4251dd224524725f11 (patch)
tree4df2798ed30c19a13c03271ee6b5b653821b5353
parent3699867372437d6fb23dc2d36fcbfcdc34d7bdc0 (diff)
downloadgcc-f57ca1ea5f9ebcd518961e4251dd224524725f11.zip
gcc-f57ca1ea5f9ebcd518961e4251dd224524725f11.tar.gz
gcc-f57ca1ea5f9ebcd518961e4251dd224524725f11.tar.bz2
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. From-SVN: r139848
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/decl.c6
-rw-r--r--gcc/cp/parser.c39
-rw-r--r--gcc/cp/pt.c17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto6.C9
6 files changed, 82 insertions, 3 deletions
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 <jason@redhat.com>
+
+ 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 <gnu@the-meissners.org>
* 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<class T, class U>
+auto add(T t, U u) -> decltype (t+u); // { dg-bogus "not declared" "" { xfail *-*-* } }