aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r--gcc/cp/decl.c64
1 files changed, 51 insertions, 13 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e664d43..f021edf 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -960,6 +960,7 @@ decls_match (tree newdecl, tree olddecl)
tree f2 = TREE_TYPE (olddecl);
tree p1 = TYPE_ARG_TYPES (f1);
tree p2 = TYPE_ARG_TYPES (f2);
+ tree r2;
/* Specializations of different templates are different functions
even if they have the same type. */
@@ -988,7 +989,14 @@ decls_match (tree newdecl, tree olddecl)
if (TREE_CODE (f1) != TREE_CODE (f2))
return 0;
- if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
+ /* A declaration with deduced return type should use its pre-deduction
+ type for declaration matching. */
+ if (FNDECL_USED_AUTO (olddecl))
+ r2 = DECL_STRUCT_FUNCTION (olddecl)->language->x_auto_return_pattern;
+ else
+ r2 = TREE_TYPE (f2);
+
+ if (same_type_p (TREE_TYPE (f1), r2))
{
if (!prototype_p (f2) && DECL_EXTERN_C_P (olddecl)
&& (DECL_BUILT_IN (olddecl)
@@ -1486,7 +1494,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
error ("new declaration %q#D", newdecl);
- error ("ambiguates old declaration %q+#D", olddecl);
+ if (FNDECL_USED_AUTO (olddecl))
+ error_at (DECL_SOURCE_LOCATION (olddecl), "ambiguates old "
+ "declaration with deduced return type");
+ else
+ error ("ambiguates old declaration %q+#D", olddecl);
return error_mark_node;
}
else
@@ -3644,10 +3656,6 @@ cxx_init_decl_processing (void)
init_list_type_node = make_node (LANG_TYPE);
record_unknown_type (init_list_type_node, "init list");
- dependent_lambda_return_type_node = make_node (LANG_TYPE);
- record_unknown_type (dependent_lambda_return_type_node,
- "undeduced lambda return type");
-
{
/* Make sure we get a unique function type, so we can give
its pointer type a name. (This wins for gdb.) */
@@ -6008,8 +6016,8 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
&& (DECL_INITIAL (decl) || init))
DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
- auto_node = type_uses_auto (type);
- if (auto_node)
+ if (TREE_CODE (decl) != FUNCTION_DECL
+ && (auto_node = type_uses_auto (type)))
{
tree d_init;
if (init == NULL_TREE)
@@ -9188,9 +9196,13 @@ grokdeclarator (const cp_declarator *declarator,
{
if (!declarator->u.function.late_return_type)
{
- error ("%qs function uses %<auto%> type specifier without"
- " trailing return type", name);
- return error_mark_node;
+ if (current_class_type
+ && LAMBDA_TYPE_P (current_class_type))
+ /* OK for C++11 lambdas. */;
+ else if (cxx_dialect < cxx1y)
+ pedwarn (input_location, 0, "%qs function uses "
+ "%<auto%> type specifier without trailing "
+ "return type", name);
}
else if (!is_auto (type))
{
@@ -10029,7 +10041,8 @@ grokdeclarator (const cp_declarator *declarator,
}
else if (decl_context == FIELD)
{
- if (!staticp && type_uses_auto (type))
+ if (!staticp && TREE_CODE (type) != METHOD_TYPE
+ && type_uses_auto (type))
{
error ("non-static data member declared %<auto%>");
type = error_mark_node;
@@ -12570,7 +12583,8 @@ check_function_type (tree decl, tree current_function_parms)
/* In a function definition, arg types must be complete. */
require_complete_types_for_parms (current_function_parms);
- if (dependent_type_p (return_type))
+ if (dependent_type_p (return_type)
+ || type_uses_auto (return_type))
return;
if (!COMPLETE_OR_VOID_TYPE_P (return_type)
|| (TYPE_FOR_JAVA (return_type) && MAYBE_CLASS_TYPE_P (return_type)))
@@ -12741,6 +12755,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
/* Build the return declaration for the function. */
restype = TREE_TYPE (fntype);
+
if (DECL_RESULT (decl1) == NULL_TREE)
{
tree resdecl;
@@ -12849,6 +12864,12 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
current_binding_level = bl;
+ if (!processing_template_decl && type_uses_auto (restype))
+ {
+ FNDECL_USED_AUTO (decl1) = true;
+ current_function_auto_return_pattern = restype;
+ }
+
/* Start the statement-tree, start the tree now. */
DECL_SAVED_TREE (decl1) = push_stmt_list ();
@@ -13463,6 +13484,23 @@ finish_function (int flags)
of curly braces for a function. */
gcc_assert (stmts_are_full_exprs_p ());
+ /* If there are no return statements in a function with auto return type,
+ the return type is void. But if the declared type is something like
+ auto*, this is an error. */
+ if (!processing_template_decl && FNDECL_USED_AUTO (fndecl)
+ && TREE_TYPE (fntype) == current_function_auto_return_pattern)
+ {
+ if (!is_auto (current_function_auto_return_pattern)
+ && !current_function_returns_value && !current_function_returns_null)
+ {
+ error ("no return statements in function returning %qT",
+ current_function_auto_return_pattern);
+ inform (input_location, "only plain %<auto%> return type can be "
+ "deduced to %<void%>");
+ }
+ apply_deduced_return_type (fndecl, void_type_node);
+ }
+
/* Save constexpr function body before it gets munged by
the NRV transformation. */
maybe_save_function_definition (fndecl);