Implement return type deduction for normal functions with -std=c++1y.
* cp-tree.h (FNDECL_USED_AUTO): New macro. (LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P): Remove. (dependent_lambda_return_type_node): Remove. (CPTI_DEPENDENT_LAMBDA_RETURN_TYPE): Remove. (struct language_function): Add x_auto_return_pattern field. (current_function_auto_return_pattern): New. (enum tsubst_flags): Add tf_partial. * decl.c (decls_match): Handle auto return comparison. (duplicate_decls): Adjust error message for auto return. (cxx_init_decl_processing): Remove dependent_lambda_return_type_node. (cp_finish_decl): Don't do auto deduction for functions. (grokdeclarator): Allow auto return without trailing return type in C++1y mode. (check_function_type): Defer checking of deduced return type. (start_preparsed_function): Set current_function_auto_return_pattern. (finish_function): Set deduced return type to void if not previously deduced. * decl2.c (change_return_type): Handle error_mark_node. (mark_used): Always instantiate functions with deduced return type. Complain about use if deduction isn't done. * parser.c (cp_parser_lambda_declarator_opt): Use 'auto' for initial return type. (cp_parser_lambda_body): Don't deduce return type in a template. (cp_parser_conversion_type_id): Allow auto in C++1y. * pt.c (instantiate_class_template_1): Don't mess with LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P. (tsubst_copy_and_build): Likewise. (fn_type_unification, tsubst): Don't reduce the template parm level of 'auto' during deduction. (unify): Compare 'auto' specially. (get_bindings): Change test. (always_instantiate_p): Always instantiate functions with deduced return type. (do_auto_deduction): Handle error_mark_node and lambda context. Don't check for use in initializer. (contains_auto_r): Remove. * search.c (lookup_conversions_r): Handle auto conversion function. * semantics.c (lambda_return_type): Handle null return. Don't mess with dependent_lambda_return_type_node. (apply_deduced_return_type): Rename from apply_lambda_return_type. * typeck.c (merge_types): Handle auto. (check_return_expr): Do auto deduction. * typeck2.c (add_exception_specifier): Fix complain check. From-SVN: r185768
This commit is contained in:
parent
8c5f232742
commit
852497a31e
@ -1,3 +1,50 @@
|
||||
2012-03-21 Jason Merrill <jason@redhat.com>
|
||||
|
||||
Implement return type deduction for normal functions with -std=c++1y.
|
||||
* cp-tree.h (FNDECL_USED_AUTO): New macro.
|
||||
(LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P): Remove.
|
||||
(dependent_lambda_return_type_node): Remove.
|
||||
(CPTI_DEPENDENT_LAMBDA_RETURN_TYPE): Remove.
|
||||
(struct language_function): Add x_auto_return_pattern field.
|
||||
(current_function_auto_return_pattern): New.
|
||||
(enum tsubst_flags): Add tf_partial.
|
||||
* decl.c (decls_match): Handle auto return comparison.
|
||||
(duplicate_decls): Adjust error message for auto return.
|
||||
(cxx_init_decl_processing): Remove dependent_lambda_return_type_node.
|
||||
(cp_finish_decl): Don't do auto deduction for functions.
|
||||
(grokdeclarator): Allow auto return without trailing return type in
|
||||
C++1y mode.
|
||||
(check_function_type): Defer checking of deduced return type.
|
||||
(start_preparsed_function): Set current_function_auto_return_pattern.
|
||||
(finish_function): Set deduced return type to void if not previously
|
||||
deduced.
|
||||
* decl2.c (change_return_type): Handle error_mark_node.
|
||||
(mark_used): Always instantiate functions with deduced return type.
|
||||
Complain about use if deduction isn't done.
|
||||
* parser.c (cp_parser_lambda_declarator_opt): Use 'auto' for
|
||||
initial return type.
|
||||
(cp_parser_lambda_body): Don't deduce return type in a template.
|
||||
(cp_parser_conversion_type_id): Allow auto in C++1y.
|
||||
* pt.c (instantiate_class_template_1): Don't mess with
|
||||
LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P.
|
||||
(tsubst_copy_and_build): Likewise.
|
||||
(fn_type_unification, tsubst): Don't reduce the template parm level
|
||||
of 'auto' during deduction.
|
||||
(unify): Compare 'auto' specially.
|
||||
(get_bindings): Change test.
|
||||
(always_instantiate_p): Always instantiate functions with deduced
|
||||
return type.
|
||||
(do_auto_deduction): Handle error_mark_node and lambda context.
|
||||
Don't check for use in initializer.
|
||||
(contains_auto_r): Remove.
|
||||
* search.c (lookup_conversions_r): Handle auto conversion function.
|
||||
* semantics.c (lambda_return_type): Handle null return. Don't mess
|
||||
with dependent_lambda_return_type_node.
|
||||
(apply_deduced_return_type): Rename from apply_lambda_return_type.
|
||||
* typeck.c (merge_types): Handle auto.
|
||||
(check_return_expr): Do auto deduction.
|
||||
* typeck2.c (add_exception_specifier): Fix complain check.
|
||||
|
||||
2012-03-22 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
PR c++/52487
|
||||
|
@ -96,8 +96,8 @@ c-common.h, not after.
|
||||
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
|
||||
STATEMENT_LIST_TRY_BLOCK (in STATEMENT_LIST)
|
||||
TYPENAME_IS_RESOLVING_P (in TYPE_NAME_TYPE)
|
||||
LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (in LAMBDA_EXPR)
|
||||
TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR)
|
||||
FNDECL_USED_AUTO (in FUNCTION_DECL)
|
||||
3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
|
||||
ICS_BAD_FLAG (in _CONV)
|
||||
FN_TRY_BLOCK_P (in TRY_BLOCK)
|
||||
@ -660,11 +660,6 @@ enum cp_lambda_default_capture_mode_type {
|
||||
#define LAMBDA_EXPR_MUTABLE_P(NODE) \
|
||||
TREE_LANG_FLAG_1 (LAMBDA_EXPR_CHECK (NODE))
|
||||
|
||||
/* True iff we should try to deduce the lambda return type from any return
|
||||
statement. */
|
||||
#define LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P(NODE) \
|
||||
TREE_LANG_FLAG_2 (LAMBDA_EXPR_CHECK (NODE))
|
||||
|
||||
/* The return type in the expression.
|
||||
* NULL_TREE indicates that none was specified. */
|
||||
#define LAMBDA_EXPR_RETURN_TYPE(NODE) \
|
||||
@ -804,7 +799,6 @@ enum cp_tree_index
|
||||
CPTI_CLASS_TYPE,
|
||||
CPTI_UNKNOWN_TYPE,
|
||||
CPTI_INIT_LIST_TYPE,
|
||||
CPTI_DEPENDENT_LAMBDA_RETURN_TYPE,
|
||||
CPTI_VTBL_TYPE,
|
||||
CPTI_VTBL_PTR_TYPE,
|
||||
CPTI_STD,
|
||||
@ -876,7 +870,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
|
||||
#define class_type_node cp_global_trees[CPTI_CLASS_TYPE]
|
||||
#define unknown_type_node cp_global_trees[CPTI_UNKNOWN_TYPE]
|
||||
#define init_list_type_node cp_global_trees[CPTI_INIT_LIST_TYPE]
|
||||
#define dependent_lambda_return_type_node cp_global_trees[CPTI_DEPENDENT_LAMBDA_RETURN_TYPE]
|
||||
#define vtbl_type_node cp_global_trees[CPTI_VTBL_TYPE]
|
||||
#define vtbl_ptr_type_node cp_global_trees[CPTI_VTBL_PTR_TYPE]
|
||||
#define std_node cp_global_trees[CPTI_STD]
|
||||
@ -1076,6 +1069,7 @@ struct GTY(()) language_function {
|
||||
tree x_in_charge_parm;
|
||||
tree x_vtt_parm;
|
||||
tree x_return_value;
|
||||
tree x_auto_return_pattern;
|
||||
|
||||
BOOL_BITFIELD returns_value : 1;
|
||||
BOOL_BITFIELD returns_null : 1;
|
||||
@ -1158,6 +1152,11 @@ struct GTY(()) language_function {
|
||||
#define current_function_return_value \
|
||||
(cp_function_chain->x_return_value)
|
||||
|
||||
/* A type involving 'auto' to be used for return type deduction. */
|
||||
|
||||
#define current_function_auto_return_pattern \
|
||||
(cp_function_chain->x_auto_return_pattern)
|
||||
|
||||
/* True if NAME is the IDENTIFIER_NODE for an overloaded "operator
|
||||
new" or "operator delete". */
|
||||
#define NEW_DELETE_OPNAME_P(NAME) \
|
||||
@ -3085,6 +3084,13 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
|
||||
#define DECL_LOCAL_FUNCTION_P(NODE) \
|
||||
DECL_LANG_FLAG_0 (FUNCTION_DECL_CHECK (NODE))
|
||||
|
||||
/* True if NODE was declared with auto in its return type, but it has
|
||||
started compilation and so the return type might have been changed by
|
||||
return type deduction; its declared return type should be found in
|
||||
DECL_STRUCT_FUNCTION(NODE)->language->x_auto_return_pattern. */
|
||||
#define FNDECL_USED_AUTO(NODE) \
|
||||
TREE_LANG_FLAG_2 (FUNCTION_DECL_CHECK (NODE))
|
||||
|
||||
/* Nonzero if NODE is a DECL which we know about but which has not
|
||||
been explicitly declared, such as a built-in function or a friend
|
||||
declared inside a class. In the latter case DECL_HIDDEN_FRIEND_P
|
||||
@ -4144,6 +4150,8 @@ enum tsubst_flags {
|
||||
conversion. */
|
||||
tf_no_access_control = 1 << 7, /* Do not perform access checks, even
|
||||
when issuing other errors. */
|
||||
tf_partial = 1 << 8, /* Doing initial explicit argument
|
||||
substitution in fn_type_unification. */
|
||||
/* Convenient substitution flags combinations. */
|
||||
tf_warning_or_error = tf_warning | tf_error
|
||||
};
|
||||
@ -5619,7 +5627,7 @@ extern tree lambda_capture_field_type (tree);
|
||||
extern tree lambda_return_type (tree);
|
||||
extern tree lambda_proxy_type (tree);
|
||||
extern tree lambda_function (tree);
|
||||
extern void apply_lambda_return_type (tree, tree);
|
||||
extern void apply_deduced_return_type (tree, tree);
|
||||
extern tree add_capture (tree, tree, tree, bool, bool);
|
||||
extern tree add_default_capture (tree, tree, tree);
|
||||
extern tree build_capture_proxy (tree);
|
||||
|
@ -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);
|
||||
|
@ -151,6 +151,9 @@ change_return_type (tree new_ret, tree fntype)
|
||||
tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
|
||||
tree attrs = TYPE_ATTRIBUTES (fntype);
|
||||
|
||||
if (new_ret == error_mark_node)
|
||||
return fntype;
|
||||
|
||||
if (same_type_p (new_ret, TREE_TYPE (fntype)))
|
||||
return fntype;
|
||||
|
||||
@ -4281,7 +4284,11 @@ mark_used (tree decl)
|
||||
if ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
|
||||
|| DECL_LANG_SPECIFIC (decl) == NULL
|
||||
|| DECL_THUNK_P (decl))
|
||||
return true;
|
||||
{
|
||||
if (!processing_template_decl && type_uses_auto (TREE_TYPE (decl)))
|
||||
error ("use of %qD before deduction of %<auto%>", decl);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* We only want to do this processing once. We don't need to keep trying
|
||||
to instantiate inline templates, because unit-at-a-time will make sure
|
||||
@ -4303,10 +4310,13 @@ mark_used (tree decl)
|
||||
/* Normally, we can wait until instantiation-time to synthesize DECL.
|
||||
However, if DECL is a static data member initialized with a constant
|
||||
or a constexpr function, we need it right now because a reference to
|
||||
such a data member or a call to such function is not value-dependent. */
|
||||
such a data member or a call to such function is not value-dependent.
|
||||
For a function that uses auto in the return type, we need to instantiate
|
||||
it to find out its type. */
|
||||
if ((decl_maybe_constant_var_p (decl)
|
||||
|| (TREE_CODE (decl) == FUNCTION_DECL
|
||||
&& DECL_DECLARED_CONSTEXPR_P (decl)))
|
||||
&& (DECL_DECLARED_CONSTEXPR_P (decl)
|
||||
|| type_uses_auto (TREE_TYPE (TREE_TYPE (decl))))))
|
||||
&& DECL_LANG_SPECIFIC (decl)
|
||||
&& DECL_TEMPLATE_INFO (decl)
|
||||
&& !uses_template_parms (DECL_TI_ARGS (decl)))
|
||||
@ -4321,6 +4331,9 @@ mark_used (tree decl)
|
||||
--function_depth;
|
||||
}
|
||||
|
||||
if (type_uses_auto (TREE_TYPE (decl)))
|
||||
error ("use of %qD before deduction of %<auto%>", decl);
|
||||
|
||||
/* If we don't need a value, then we don't need to synthesize DECL. */
|
||||
if (cp_unevaluated_operand != 0)
|
||||
return true;
|
||||
|
@ -8416,9 +8416,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
|
||||
if (LAMBDA_EXPR_RETURN_TYPE (lambda_expr))
|
||||
return_type_specs.type = LAMBDA_EXPR_RETURN_TYPE (lambda_expr);
|
||||
else
|
||||
/* Maybe we will deduce the return type later, but we can use void
|
||||
as a placeholder return type anyways. */
|
||||
return_type_specs.type = void_type_node;
|
||||
/* Maybe we will deduce the return type later. */
|
||||
return_type_specs.type = make_auto ();
|
||||
|
||||
p = obstack_alloc (&declarator_obstack, 0);
|
||||
|
||||
@ -8539,7 +8538,8 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
|
||||
|
||||
if (cp_parser_parse_definitely (parser))
|
||||
{
|
||||
apply_lambda_return_type (lambda_expr, lambda_return_type (expr));
|
||||
if (!processing_template_decl)
|
||||
apply_deduced_return_type (fco, lambda_return_type (expr));
|
||||
|
||||
/* Will get error here if type not deduced yet. */
|
||||
finish_return_stmt (expr);
|
||||
@ -8550,13 +8550,10 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
|
||||
|
||||
if (!done)
|
||||
{
|
||||
if (!LAMBDA_EXPR_RETURN_TYPE (lambda_expr))
|
||||
LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda_expr) = true;
|
||||
while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL))
|
||||
cp_parser_label_declaration (parser);
|
||||
cp_parser_statement_seq_opt (parser, NULL_TREE);
|
||||
cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
|
||||
LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda_expr) = false;
|
||||
}
|
||||
|
||||
finish_compound_stmt (compound_stmt);
|
||||
@ -11275,8 +11272,14 @@ cp_parser_conversion_type_id (cp_parser* parser)
|
||||
if (! cp_parser_uncommitted_to_tentative_parse_p (parser)
|
||||
&& type_uses_auto (type_specified))
|
||||
{
|
||||
error ("invalid use of %<auto%> in conversion operator");
|
||||
return error_mark_node;
|
||||
if (cxx_dialect < cxx1y)
|
||||
{
|
||||
error ("invalid use of %<auto%> in conversion operator");
|
||||
return error_mark_node;
|
||||
}
|
||||
else if (template_parm_scope_p ())
|
||||
warning (0, "use of %<auto%> in member template "
|
||||
"conversion operator can never be deduced");
|
||||
}
|
||||
|
||||
return type_specified;
|
||||
|
78
gcc/cp/pt.c
78
gcc/cp/pt.c
@ -9112,12 +9112,6 @@ instantiate_class_template_1 (tree type)
|
||||
tree decl = lambda_function (type);
|
||||
if (decl)
|
||||
{
|
||||
tree lambda = CLASSTYPE_LAMBDA_EXPR (type);
|
||||
if (LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda))
|
||||
{
|
||||
apply_lambda_return_type (lambda, void_type_node);
|
||||
LAMBDA_EXPR_RETURN_TYPE (lambda) = NULL_TREE;
|
||||
}
|
||||
instantiate_decl (decl, false, false);
|
||||
maybe_add_lambda_conv_op (type);
|
||||
}
|
||||
@ -11331,6 +11325,12 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
||||
about the template parameter in question. */
|
||||
return t;
|
||||
|
||||
/* Early in template argument deduction substitution, we don't
|
||||
want to reduce the level of 'auto', or it will be confused
|
||||
with a normal template parm in subsequent deduction. */
|
||||
if (is_auto (t) && (complain & tf_partial))
|
||||
return t;
|
||||
|
||||
/* If we get here, we must have been looking at a parm for a
|
||||
more deeply nested template. Make a new version of this
|
||||
template parameter, but with a lower level. */
|
||||
@ -14334,14 +14334,8 @@ tsubst_copy_and_build (tree t,
|
||||
= (LAMBDA_EXPR_DISCRIMINATOR (t));
|
||||
LAMBDA_EXPR_EXTRA_SCOPE (r)
|
||||
= RECUR (LAMBDA_EXPR_EXTRA_SCOPE (t));
|
||||
if (LAMBDA_EXPR_RETURN_TYPE (t) == dependent_lambda_return_type_node)
|
||||
{
|
||||
LAMBDA_EXPR_RETURN_TYPE (r) = dependent_lambda_return_type_node;
|
||||
LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (r) = true;
|
||||
}
|
||||
else
|
||||
LAMBDA_EXPR_RETURN_TYPE (r)
|
||||
= tsubst (LAMBDA_EXPR_RETURN_TYPE (t), args, complain, in_decl);
|
||||
LAMBDA_EXPR_RETURN_TYPE (r)
|
||||
= tsubst (LAMBDA_EXPR_RETURN_TYPE (t), args, complain, in_decl);
|
||||
|
||||
gcc_assert (LAMBDA_EXPR_THIS_CAPTURE (t) == NULL_TREE
|
||||
&& LAMBDA_EXPR_PENDING_PROXIES (t) == NULL);
|
||||
@ -14860,7 +14854,7 @@ fn_type_unification (tree fn,
|
||||
fntype = deduction_tsubst_fntype (fn, converted_args,
|
||||
(explain_p
|
||||
? tf_warning_or_error
|
||||
: tf_none));
|
||||
: tf_none) | tf_partial);
|
||||
processing_template_decl -= incomplete;
|
||||
|
||||
if (fntype == error_mark_node)
|
||||
@ -16275,7 +16269,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
|
||||
to see if it matches ARG. */
|
||||
{
|
||||
if (TREE_CODE (arg) == TREE_CODE (parm)
|
||||
&& same_type_p (parm, arg))
|
||||
&& (is_auto (parm) ? is_auto (arg)
|
||||
: same_type_p (parm, arg)))
|
||||
return unify_success (explain_p);
|
||||
else
|
||||
return unify_type_mismatch (explain_p, parm, arg);
|
||||
@ -17408,7 +17403,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
|
||||
The call to fn_type_unification will handle substitution into the
|
||||
FN. */
|
||||
decl_type = TREE_TYPE (decl);
|
||||
if (explicit_args && uses_template_parms (decl_type))
|
||||
if (explicit_args && decl == DECL_TEMPLATE_RESULT (fn))
|
||||
{
|
||||
tree tmpl;
|
||||
tree converted_args;
|
||||
@ -18315,7 +18310,8 @@ always_instantiate_p (tree decl)
|
||||
that for "extern template" functions. Therefore, we check
|
||||
DECL_DECLARED_INLINE_P, rather than possibly_inlined_p. */
|
||||
return ((TREE_CODE (decl) == FUNCTION_DECL
|
||||
&& DECL_DECLARED_INLINE_P (decl))
|
||||
&& (DECL_DECLARED_INLINE_P (decl)
|
||||
|| type_uses_auto (TREE_TYPE (TREE_TYPE (decl)))))
|
||||
/* And we need to instantiate static data members so that
|
||||
their initializers are available in integral constant
|
||||
expressions. */
|
||||
@ -20269,20 +20265,6 @@ listify_autos (tree type, tree auto_node)
|
||||
return tsubst (type, argvec, tf_warning_or_error, NULL_TREE);
|
||||
}
|
||||
|
||||
/* walk_tree helper for do_auto_deduction. */
|
||||
|
||||
static tree
|
||||
contains_auto_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
|
||||
void *type)
|
||||
{
|
||||
/* Is this a variable with the type we're looking for? */
|
||||
if (DECL_P (*tp)
|
||||
&& TREE_TYPE (*tp) == type)
|
||||
return *tp;
|
||||
else
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Replace occurrences of 'auto' in TYPE with the appropriate type deduced
|
||||
from INIT. AUTO_NODE is the TEMPLATE_TYPE_PARM used for 'auto' in TYPE. */
|
||||
|
||||
@ -20291,25 +20273,17 @@ do_auto_deduction (tree type, tree init, tree auto_node)
|
||||
{
|
||||
tree parms, tparms, targs;
|
||||
tree args[1];
|
||||
tree decl;
|
||||
int val;
|
||||
|
||||
if (init == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
if (processing_template_decl
|
||||
&& (TREE_TYPE (init) == NULL_TREE
|
||||
|| BRACE_ENCLOSED_INITIALIZER_P (init)))
|
||||
/* Not enough information to try this yet. */
|
||||
return type;
|
||||
|
||||
/* The name of the object being declared shall not appear in the
|
||||
initializer expression. */
|
||||
decl = cp_walk_tree_without_duplicates (&init, contains_auto_r, type);
|
||||
if (decl)
|
||||
{
|
||||
error ("variable %q#D with %<auto%> type used in its own "
|
||||
"initializer", decl);
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* [dcl.spec.auto]: Obtain P from T by replacing the occurrences of auto
|
||||
with either a new invented type template parameter U or, if the
|
||||
initializer is a braced-init-list (8.5.4), with
|
||||
@ -20337,7 +20311,13 @@ do_auto_deduction (tree type, tree init, tree auto_node)
|
||||
/* If type is error_mark_node a diagnostic must have been
|
||||
emitted by now. Also, having a mention to '<type error>'
|
||||
in the diagnostic is not really useful to the user. */
|
||||
error ("unable to deduce %qT from %qE", type, init);
|
||||
{
|
||||
if (cfun && auto_node == current_function_auto_return_pattern
|
||||
&& LAMBDA_FUNCTION_P (current_function_decl))
|
||||
error ("unable to deduce lambda return type from %qE", init);
|
||||
else
|
||||
error ("unable to deduce %qT from %qE", type, init);
|
||||
}
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
@ -20348,8 +20328,14 @@ do_auto_deduction (tree type, tree init, tree auto_node)
|
||||
if (TREE_TYPE (auto_node)
|
||||
&& !same_type_p (TREE_TYPE (auto_node), TREE_VEC_ELT (targs, 0)))
|
||||
{
|
||||
error ("inconsistent deduction for %qT: %qT and then %qT",
|
||||
auto_node, TREE_TYPE (auto_node), TREE_VEC_ELT (targs, 0));
|
||||
if (cfun && auto_node == current_function_auto_return_pattern
|
||||
&& LAMBDA_FUNCTION_P (current_function_decl))
|
||||
error ("inconsistent types %qT and %qT deduced for "
|
||||
"lambda return type", TREE_TYPE (auto_node),
|
||||
TREE_VEC_ELT (targs, 0));
|
||||
else
|
||||
error ("inconsistent deduction for %qT: %qT and then %qT",
|
||||
auto_node, TREE_TYPE (auto_node), TREE_VEC_ELT (targs, 0));
|
||||
return error_mark_node;
|
||||
}
|
||||
TREE_TYPE (auto_node) = TREE_VEC_ELT (targs, 0);
|
||||
|
@ -2430,6 +2430,11 @@ lookup_conversions_r (tree binfo,
|
||||
if (!IDENTIFIER_MARKED (name))
|
||||
{
|
||||
tree type = DECL_CONV_FN_TYPE (cur);
|
||||
if (type_uses_auto (type))
|
||||
{
|
||||
mark_used (cur);
|
||||
type = DECL_CONV_FN_TYPE (cur);
|
||||
}
|
||||
|
||||
if (check_hidden_convs (binfo, virtual_depth, virtualness,
|
||||
type, parent_convs, other_convs))
|
||||
|
@ -8691,18 +8691,16 @@ begin_lambda_type (tree lambda)
|
||||
tree
|
||||
lambda_return_type (tree expr)
|
||||
{
|
||||
tree type;
|
||||
if (expr == NULL_TREE)
|
||||
return void_type_node;
|
||||
if (type_unknown_p (expr)
|
||||
|| BRACE_ENCLOSED_INITIALIZER_P (expr))
|
||||
{
|
||||
cxx_incomplete_type_error (expr, TREE_TYPE (expr));
|
||||
return void_type_node;
|
||||
}
|
||||
if (type_dependent_expression_p (expr))
|
||||
type = dependent_lambda_return_type_node;
|
||||
else
|
||||
type = cv_unqualified (type_decays_to (unlowered_expr_type (expr)));
|
||||
return type;
|
||||
gcc_checking_assert (!type_dependent_expression_p (expr));
|
||||
return cv_unqualified (type_decays_to (unlowered_expr_type (expr)));
|
||||
}
|
||||
|
||||
/* Given a LAMBDA_EXPR or closure type LAMBDA, return the op() of the
|
||||
@ -8749,29 +8747,32 @@ lambda_capture_field_type (tree expr)
|
||||
return type;
|
||||
}
|
||||
|
||||
/* Recompute the return type for LAMBDA with body of the form:
|
||||
{ return EXPR ; } */
|
||||
/* Insert the deduced return type for an auto function. */
|
||||
|
||||
void
|
||||
apply_lambda_return_type (tree lambda, tree return_type)
|
||||
apply_deduced_return_type (tree fco, tree return_type)
|
||||
{
|
||||
tree fco = lambda_function (lambda);
|
||||
tree result;
|
||||
|
||||
LAMBDA_EXPR_RETURN_TYPE (lambda) = return_type;
|
||||
|
||||
if (return_type == error_mark_node)
|
||||
return;
|
||||
if (TREE_TYPE (TREE_TYPE (fco)) == return_type)
|
||||
return;
|
||||
|
||||
/* TREE_TYPE (FUNCTION_DECL) == METHOD_TYPE
|
||||
TREE_TYPE (METHOD_TYPE) == return-type */
|
||||
if (LAMBDA_FUNCTION_P (fco))
|
||||
{
|
||||
tree lambda = CLASSTYPE_LAMBDA_EXPR (current_class_type);
|
||||
LAMBDA_EXPR_RETURN_TYPE (lambda) = return_type;
|
||||
}
|
||||
|
||||
if (DECL_CONV_FN_P (fco))
|
||||
DECL_NAME (fco) = mangle_conv_op_name_for_type (return_type);
|
||||
|
||||
TREE_TYPE (fco) = change_return_type (return_type, TREE_TYPE (fco));
|
||||
|
||||
result = DECL_RESULT (fco);
|
||||
if (result == NULL_TREE)
|
||||
return;
|
||||
if (TREE_TYPE (result) == return_type)
|
||||
return;
|
||||
|
||||
/* We already have a DECL_RESULT from start_preparsed_function.
|
||||
Now we need to redo the work it and allocate_struct_function
|
||||
@ -8786,12 +8787,13 @@ apply_lambda_return_type (tree lambda, tree return_type)
|
||||
|
||||
DECL_RESULT (fco) = result;
|
||||
|
||||
if (!processing_template_decl && aggregate_value_p (result, fco))
|
||||
if (!processing_template_decl)
|
||||
{
|
||||
bool aggr = aggregate_value_p (result, fco);
|
||||
#ifdef PCC_STATIC_STRUCT_RETURN
|
||||
cfun->returns_pcc_struct = 1;
|
||||
cfun->returns_pcc_struct = aggr;
|
||||
#endif
|
||||
cfun->returns_struct = 1;
|
||||
cfun->returns_struct = aggr;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -733,6 +733,11 @@ merge_types (tree t1, tree t2)
|
||||
if (t2 == error_mark_node)
|
||||
return t1;
|
||||
|
||||
/* Handle merging an auto redeclaration with a previous deduced
|
||||
return type. */
|
||||
if (is_auto (t1))
|
||||
return t2;
|
||||
|
||||
/* Merge the attributes. */
|
||||
attributes = (*targetm.merge_type_attributes) (t1, t2);
|
||||
|
||||
@ -7779,9 +7784,11 @@ tree
|
||||
check_return_expr (tree retval, bool *no_warning)
|
||||
{
|
||||
tree result;
|
||||
/* The type actually returned by the function, after any
|
||||
promotions. */
|
||||
/* The type actually returned by the function. */
|
||||
tree valtype;
|
||||
/* The type the function is declared to return, or void if
|
||||
the declared type is incomplete. */
|
||||
tree functype;
|
||||
int fn_returns_value_p;
|
||||
bool named_return_value_okay_p;
|
||||
|
||||
@ -7812,30 +7819,6 @@ check_return_expr (tree retval, bool *no_warning)
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* As an extension, deduce lambda return type from a return statement
|
||||
anywhere in the body. */
|
||||
if (retval && LAMBDA_FUNCTION_P (current_function_decl))
|
||||
{
|
||||
tree lambda = CLASSTYPE_LAMBDA_EXPR (current_class_type);
|
||||
if (LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda))
|
||||
{
|
||||
tree type = lambda_return_type (retval);
|
||||
tree oldtype = LAMBDA_EXPR_RETURN_TYPE (lambda);
|
||||
|
||||
if (oldtype == NULL_TREE)
|
||||
apply_lambda_return_type (lambda, type);
|
||||
/* If one of the answers is type-dependent, we can't do any
|
||||
better until instantiation time. */
|
||||
else if (oldtype == dependent_lambda_return_type_node)
|
||||
/* Leave it. */;
|
||||
else if (type == dependent_lambda_return_type_node)
|
||||
apply_lambda_return_type (lambda, type);
|
||||
else if (!same_type_p (type, oldtype))
|
||||
error ("inconsistent types %qT and %qT deduced for "
|
||||
"lambda return type", type, oldtype);
|
||||
}
|
||||
}
|
||||
|
||||
if (processing_template_decl)
|
||||
{
|
||||
current_function_returns_value = 1;
|
||||
@ -7844,6 +7827,42 @@ check_return_expr (tree retval, bool *no_warning)
|
||||
return retval;
|
||||
}
|
||||
|
||||
functype = TREE_TYPE (TREE_TYPE (current_function_decl));
|
||||
|
||||
/* Deduce auto return type from a return statement. */
|
||||
if (current_function_auto_return_pattern)
|
||||
{
|
||||
tree auto_node;
|
||||
tree type;
|
||||
|
||||
if (!retval && !is_auto (current_function_auto_return_pattern))
|
||||
{
|
||||
/* Give a helpful error message. */
|
||||
error ("return-statement with no value, in function returning %qT",
|
||||
current_function_auto_return_pattern);
|
||||
inform (input_location, "only plain %<auto%> return type can be "
|
||||
"deduced to %<void%>");
|
||||
type = error_mark_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!retval)
|
||||
retval = void_zero_node;
|
||||
auto_node = type_uses_auto (current_function_auto_return_pattern);
|
||||
type = do_auto_deduction (current_function_auto_return_pattern,
|
||||
retval, auto_node);
|
||||
}
|
||||
|
||||
if (type == error_mark_node)
|
||||
/* Leave it. */;
|
||||
else if (functype == current_function_auto_return_pattern)
|
||||
apply_deduced_return_type (current_function_decl, type);
|
||||
else
|
||||
/* A mismatch should have been diagnosed in do_auto_deduction. */
|
||||
gcc_assert (same_type_p (type, functype));
|
||||
functype = type;
|
||||
}
|
||||
|
||||
/* When no explicit return-value is given in a function with a named
|
||||
return value, the named return value is used. */
|
||||
result = DECL_RESULT (current_function_decl);
|
||||
@ -7857,12 +7876,11 @@ check_return_expr (tree retval, bool *no_warning)
|
||||
that's supposed to return a value. */
|
||||
if (!retval && fn_returns_value_p)
|
||||
{
|
||||
permerror (input_location, "return-statement with no value, in function returning %qT",
|
||||
valtype);
|
||||
/* Clear this, so finish_function won't say that we reach the
|
||||
end of a non-void function (which we don't, we gave a
|
||||
return!). */
|
||||
current_function_returns_null = 0;
|
||||
if (functype != error_mark_node)
|
||||
permerror (input_location, "return-statement with no value, in "
|
||||
"function returning %qT", valtype);
|
||||
/* Remember that this function did return. */
|
||||
current_function_returns_value = 1;
|
||||
/* And signal caller that TREE_NO_WARNING should be set on the
|
||||
RETURN_EXPR to avoid control reaches end of non-void function
|
||||
warnings in tree-cfg.c. */
|
||||
@ -7963,14 +7981,12 @@ check_return_expr (tree retval, bool *no_warning)
|
||||
&& DECL_CONTEXT (retval) == current_function_decl
|
||||
&& ! TREE_STATIC (retval)
|
||||
&& ! DECL_ANON_UNION_VAR_P (retval)
|
||||
&& (DECL_ALIGN (retval)
|
||||
>= DECL_ALIGN (DECL_RESULT (current_function_decl)))
|
||||
&& (DECL_ALIGN (retval) >= DECL_ALIGN (result))
|
||||
/* The cv-unqualified type of the returned value must be the
|
||||
same as the cv-unqualified return type of the
|
||||
function. */
|
||||
&& same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
|
||||
(TYPE_MAIN_VARIANT
|
||||
(TREE_TYPE (TREE_TYPE (current_function_decl)))))
|
||||
(TYPE_MAIN_VARIANT (functype)))
|
||||
/* And the returned value must be non-volatile. */
|
||||
&& ! TYPE_VOLATILE (TREE_TYPE (retval)));
|
||||
|
||||
@ -7995,8 +8011,6 @@ check_return_expr (tree retval, bool *no_warning)
|
||||
;
|
||||
else
|
||||
{
|
||||
/* The type the function is declared to return. */
|
||||
tree functype = TREE_TYPE (TREE_TYPE (current_function_decl));
|
||||
int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
|
||||
|
||||
/* The functype's return type will have been set to void, if it
|
||||
@ -8016,10 +8030,9 @@ check_return_expr (tree retval, bool *no_warning)
|
||||
&& DECL_CONTEXT (retval) == current_function_decl
|
||||
&& !TREE_STATIC (retval)
|
||||
&& same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
|
||||
(TYPE_MAIN_VARIANT
|
||||
(TREE_TYPE (TREE_TYPE (current_function_decl)))))
|
||||
(TYPE_MAIN_VARIANT (functype)))
|
||||
/* This is only interesting for class type. */
|
||||
&& CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
|
||||
&& CLASS_TYPE_P (functype))
|
||||
flags = flags | LOOKUP_PREFER_RVALUE;
|
||||
|
||||
/* First convert the value to the function's return type, then
|
||||
|
@ -1818,7 +1818,8 @@ add_exception_specifier (tree list, tree spec, int complain)
|
||||
else
|
||||
diag_type = DK_ERROR; /* error */
|
||||
|
||||
if (diag_type != DK_UNSPECIFIED && complain)
|
||||
if (diag_type != DK_UNSPECIFIED
|
||||
&& (complain & tf_warning_or_error))
|
||||
cxx_incomplete_type_diagnostic (NULL_TREE, core, diag_type);
|
||||
|
||||
return list;
|
||||
|
@ -1,3 +1,20 @@
|
||||
2012-03-21 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* g++.dg/cpp0x/auto3.C: Compile with -pedantic-errors.
|
||||
* g++.dg/cpp0x/trailing2.C: Likewise.
|
||||
* g++.dg/warn/pr23075.C: Change dg-warning to dg-bogus.
|
||||
* g++.dg/cpp1y/auto-fn1.C: New.
|
||||
* g++.dg/cpp1y/auto-fn2.C: New.
|
||||
* g++.dg/cpp1y/auto-fn3.C: New.
|
||||
* g++.dg/cpp1y/auto-fn4.C: New.
|
||||
* g++.dg/cpp1y/auto-fn5.C: New.
|
||||
* g++.dg/cpp1y/auto-fn6.C: New.
|
||||
* g++.dg/cpp1y/auto-fn7.C: New.
|
||||
* g++.dg/cpp1y/auto-fn8.C: New.
|
||||
* g++.dg/cpp1y/auto-fn9.C: New.
|
||||
* g++.dg/cpp1y/auto-fn10.C: New.
|
||||
* g++.dg/cpp1y/auto-fn11.C: New.
|
||||
|
||||
2012-03-23 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/52678
|
||||
|
@ -2,5 +2,5 @@
|
||||
|
||||
void f()
|
||||
{
|
||||
auto val = val; // { dg-error "auto. type used in its own initializer" }
|
||||
auto val = val; // { dg-error "auto" }
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Negative test for auto
|
||||
// { dg-options "-std=c++0x" }
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
@ -10,7 +10,7 @@ auto x; // { dg-error "auto" }
|
||||
auto i = 42, j = 42.0; // { dg-error "auto" }
|
||||
|
||||
// New CWG issue
|
||||
auto a[2] = { 1, 2 }; // { dg-error "initializer_list" }
|
||||
auto a[2] = { 1, 2 }; // { dg-error "auto|initializer_list" }
|
||||
|
||||
template<class T>
|
||||
struct A { };
|
||||
|
@ -1,6 +1,6 @@
|
||||
// PR c++/37967
|
||||
// Negative test for auto
|
||||
// { dg-options "-std=c++0x" }
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
auto f1 () -> int;
|
||||
auto f2 (); // { dg-error "without trailing return type" }
|
||||
|
5
gcc/testsuite/g++.dg/cpp1y/auto-fn1.C
Normal file
5
gcc/testsuite/g++.dg/cpp1y/auto-fn1.C
Normal file
@ -0,0 +1,5 @@
|
||||
// { dg-options -std=c++1y }
|
||||
|
||||
constexpr auto f() { return (char)42; }
|
||||
#define SA(X) static_assert ((X),#X)
|
||||
SA (f() == 42);
|
16
gcc/testsuite/g++.dg/cpp1y/auto-fn10.C
Normal file
16
gcc/testsuite/g++.dg/cpp1y/auto-fn10.C
Normal file
@ -0,0 +1,16 @@
|
||||
// A template declared with auto should be declared with auto in an
|
||||
// explicit instantiation or explicit specialization, too.
|
||||
// { dg-options -std=c++1y }
|
||||
|
||||
template <class T>
|
||||
auto f(T t) { return t; }
|
||||
|
||||
template<> auto f<int>(int);
|
||||
template auto f<float>(float);
|
||||
template<> auto f(int*);
|
||||
template auto f(float*);
|
||||
|
||||
template<> short f<short>(short); // { dg-error "does not match" }
|
||||
template char f<char>(char); // { dg-error "does not match" }
|
||||
template<> short f(short*); // { dg-error "does not match" }
|
||||
template char f(char*); // { dg-error "does not match" }
|
5
gcc/testsuite/g++.dg/cpp1y/auto-fn11.C
Normal file
5
gcc/testsuite/g++.dg/cpp1y/auto-fn11.C
Normal file
@ -0,0 +1,5 @@
|
||||
// { dg-options -std=c++1y }
|
||||
|
||||
auto f() { return; } // OK, return type is void
|
||||
auto* g() { return; } // { dg-error "no value" }
|
||||
auto* h() { } // { dg-error "no return statements" }
|
14
gcc/testsuite/g++.dg/cpp1y/auto-fn12.C
Normal file
14
gcc/testsuite/g++.dg/cpp1y/auto-fn12.C
Normal file
@ -0,0 +1,14 @@
|
||||
// { dg-options -std=c++1y }
|
||||
// { dg-final { scan-assembler "_ZN1AIiEcviEv" } }
|
||||
|
||||
template <class T>
|
||||
struct A {
|
||||
T t;
|
||||
operator auto() { return t+1; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
int i = A<int>{42};
|
||||
return (i != 43);
|
||||
}
|
6
gcc/testsuite/g++.dg/cpp1y/auto-fn13.C
Normal file
6
gcc/testsuite/g++.dg/cpp1y/auto-fn13.C
Normal file
@ -0,0 +1,6 @@
|
||||
// { dg-options -std=c++1y }
|
||||
|
||||
struct A {
|
||||
template <class T>
|
||||
operator auto() { return T(); } // { dg-warning "auto.*template" }
|
||||
};
|
3
gcc/testsuite/g++.dg/cpp1y/auto-fn2.C
Normal file
3
gcc/testsuite/g++.dg/cpp1y/auto-fn2.C
Normal file
@ -0,0 +1,3 @@
|
||||
// { dg-options -std=c++1y }
|
||||
|
||||
auto f() { return f(); } // { dg-error "auto" }
|
10
gcc/testsuite/g++.dg/cpp1y/auto-fn3.C
Normal file
10
gcc/testsuite/g++.dg/cpp1y/auto-fn3.C
Normal file
@ -0,0 +1,10 @@
|
||||
// { dg-options -std=c++1y }
|
||||
|
||||
bool b;
|
||||
auto f()
|
||||
{
|
||||
if (b)
|
||||
return 42;
|
||||
else
|
||||
return f();
|
||||
}
|
7
gcc/testsuite/g++.dg/cpp1y/auto-fn4.C
Normal file
7
gcc/testsuite/g++.dg/cpp1y/auto-fn4.C
Normal file
@ -0,0 +1,7 @@
|
||||
// { dg-options -std=c++1y }
|
||||
|
||||
template <class T>
|
||||
constexpr auto f(T t) { return t+1; }
|
||||
|
||||
#define SA(X) static_assert((X),#X)
|
||||
SA(f(1)==2);
|
11
gcc/testsuite/g++.dg/cpp1y/auto-fn5.C
Normal file
11
gcc/testsuite/g++.dg/cpp1y/auto-fn5.C
Normal file
@ -0,0 +1,11 @@
|
||||
// { dg-options -std=c++1y }
|
||||
// { dg-do run }
|
||||
|
||||
int i;
|
||||
auto& f() { return i; }
|
||||
|
||||
int main()
|
||||
{
|
||||
f() = 42;
|
||||
return i != 42;
|
||||
}
|
18
gcc/testsuite/g++.dg/cpp1y/auto-fn6.C
Normal file
18
gcc/testsuite/g++.dg/cpp1y/auto-fn6.C
Normal file
@ -0,0 +1,18 @@
|
||||
// { dg-options -std=c++1y }
|
||||
|
||||
template <class T, class U> struct ST;
|
||||
template <class T> struct ST<T,T> {};
|
||||
|
||||
int g(int);
|
||||
char& g(char);
|
||||
double&& g(double);
|
||||
|
||||
template <class T> auto&& f(T t)
|
||||
{ return g(t); } // { dg-warning "reference to temporary" }
|
||||
|
||||
int main()
|
||||
{
|
||||
ST<decltype(f(1)),int&&>();
|
||||
ST<decltype(f('\0')),char&>();
|
||||
ST<decltype(f(1.0)),double&&>();
|
||||
}
|
5
gcc/testsuite/g++.dg/cpp1y/auto-fn7.C
Normal file
5
gcc/testsuite/g++.dg/cpp1y/auto-fn7.C
Normal file
@ -0,0 +1,5 @@
|
||||
// { dg-options "-std=c++1y -pedantic-errors" }
|
||||
|
||||
auto f();
|
||||
|
||||
template <class T> auto f(T);
|
13
gcc/testsuite/g++.dg/cpp1y/auto-fn8.C
Normal file
13
gcc/testsuite/g++.dg/cpp1y/auto-fn8.C
Normal file
@ -0,0 +1,13 @@
|
||||
// { dg-options "-std=c++1y -pedantic-errors" }
|
||||
|
||||
auto f() { return 42; } // { dg-error "deduced return type" }
|
||||
auto f(); // OK
|
||||
int f(); // { dg-error "new declaration" }
|
||||
|
||||
template <class T> auto f(T t) { return t; }
|
||||
template <class T> T f(T t);
|
||||
|
||||
int main()
|
||||
{
|
||||
f(42); // { dg-error "ambiguous" }
|
||||
}
|
11
gcc/testsuite/g++.dg/cpp1y/auto-fn9.C
Normal file
11
gcc/testsuite/g++.dg/cpp1y/auto-fn9.C
Normal file
@ -0,0 +1,11 @@
|
||||
// { dg-options -std=c++1y }
|
||||
// { dg-final { scan-assembler "_Z1fIiERDaRKT_S1_" } }
|
||||
|
||||
template <class T>
|
||||
auto& f(const T& t, T u) { return t; }
|
||||
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
f(i,i);
|
||||
}
|
@ -6,7 +6,7 @@ template<int> void
|
||||
foo ()
|
||||
{
|
||||
#pragma omp parallel for
|
||||
for (auto i = i = 0; i<4; ++i) // { dg-error "incomplete|unable|invalid" }
|
||||
for (auto i = i = 0; i<4; ++i) // { dg-error "incomplete|unable|invalid|auto" }
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -6,4 +6,4 @@ int
|
||||
foo (void)
|
||||
{
|
||||
return; // { dg-error "with no value" }
|
||||
} // { dg-warning "no return statement" }
|
||||
} // { dg-bogus "no return statement" }
|
||||
|
@ -10,6 +10,6 @@ struct S
|
||||
|
||||
template <class T>
|
||||
template <> // { dg-error "enclosing class templates|invalid explicit specialization" }
|
||||
void S<T>::f<int> () // { dg-error "does not match|invalid function declaration" }
|
||||
void S<T>::f<int> ()
|
||||
{
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user