diff options
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r-- | gcc/cp/decl.c | 64 |
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); |