Implement late-specified return type using 'auto'.
authorJason Merrill <jason@redhat.com>
Mon, 1 Sep 2008 03:33:19 +0000 (23:33 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 1 Sep 2008 03:33:19 +0000 (23:33 -0400)
        * 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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp0x/auto6.C [new file with mode: 0644]

index 30c6aa6..898beb0 100644 (file)
@@ -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
index 37bed91..a01d981 100644 (file)
@@ -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);
index 5a5a41f..0d735c4 100644 (file)
@@ -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;
index 08ec967..3d74d6c 100644 (file)
@@ -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:
index 5bb18d9..b05c7a0 100644 (file)
@@ -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 (file)
index 0000000..ac20993
--- /dev/null
@@ -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 *-*-* } }