From b344d949d25164341ca4532ce067af1b254198a0 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 8 Sep 2008 16:52:44 -0400 Subject: [PATCH] re PR c++/37302 (function parameters are declared too late) PR c++/37302 * parser.c (cp_parser_parameter_declaration_list): Process the PARM_DECLs as we go and push them. Return a TREE_LIST. (cp_parser_parameter_declaration_clause): Return a TREE_LIST. (cp_parser_direct_declarator): Create a binding level and suppress deprecated warnings in the parameter list. (make_call_declarator): PARMS is now a tree. * cp-tree.h (struct cp_declarator): Function parms are now a tree. * decl.h (enum deprecated_states, deprecated_state): Move here. * decl.c: From here. (type_is_deprecated): New fn. (grokparms): PARMLIST is a tree now. Warn about parms that use deprecated types. * mangle.c (write_expression): Handle PARM_DECL, CALL_EXPR and 0-operand cast. * pt.c (tsubst) [DECLTYPE_TYPE]: Set skip_evaluation. (tsubst_copy) [PARM_DECL]: Handle a PARM_DECL used outside of a function. * name-lookup.c (pushtag): Look through function parameter scopes. (pushdecl_maybe_friend): Don't set DECL_CONTEXT on a PARM_DECL when we're parsing a function declarator. From-SVN: r140120 --- gcc/cp/ChangeLog | 24 ++++++ gcc/cp/cp-tree.h | 4 +- gcc/cp/decl.c | 81 ++++++++++--------- gcc/cp/decl.h | 13 +++ gcc/cp/mangle.c | 28 +++++-- gcc/cp/name-lookup.c | 11 ++- gcc/cp/parser.c | 80 ++++++++++++------ gcc/cp/pt.c | 32 ++++++-- gcc/testsuite/g++.dg/cpp0x/auto2.C | 2 + gcc/testsuite/g++.dg/cpp0x/auto3.C | 4 + gcc/testsuite/g++.dg/cpp0x/auto6.C | 18 ++++- gcc/testsuite/g++.dg/other/error15.C | 68 ++++++++-------- gcc/testsuite/g++.dg/other/error6.C | 3 +- gcc/testsuite/g++.dg/other/pr28114.C | 2 +- gcc/testsuite/g++.dg/parse/error3.C | 12 +-- gcc/testsuite/g++.old-deja/g++.jason/rfg16.C | 4 +- .../g++.old-deja/g++.oliva/template1.C | 2 +- gcc/testsuite/g++.old-deja/g++.pt/memtemp29.C | 2 +- 18 files changed, 260 insertions(+), 130 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cb5c31402e8..cd5b52cbb8a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,27 @@ +2008-09-06 Jason Merrill + + PR c++/37302 + * parser.c (cp_parser_parameter_declaration_list): Process the + PARM_DECLs as we go and push them. Return a TREE_LIST. + (cp_parser_parameter_declaration_clause): Return a TREE_LIST. + (cp_parser_direct_declarator): Create a binding level and + suppress deprecated warnings in the parameter list. + (make_call_declarator): PARMS is now a tree. + * cp-tree.h (struct cp_declarator): Function parms are now a tree. + * decl.h (enum deprecated_states, deprecated_state): Move here. + * decl.c: From here. + (type_is_deprecated): New fn. + (grokparms): PARMLIST is a tree now. Warn about parms that + use deprecated types. + * mangle.c (write_expression): Handle PARM_DECL, CALL_EXPR and + 0-operand cast. + * pt.c (tsubst) [DECLTYPE_TYPE]: Set skip_evaluation. + (tsubst_copy) [PARM_DECL]: Handle a PARM_DECL used outside of a + function. + * name-lookup.c (pushtag): Look through function parameter scopes. + (pushdecl_maybe_friend): Don't set DECL_CONTEXT on a PARM_DECL + when we're parsing a function declarator. + 2008-09-05 Douglas Gregor PR c++/37342 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ca069b765cf..4f6716b4c5b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4108,8 +4108,8 @@ struct cp_declarator { } id; /* For functions. */ struct { - /* The parameters to the function. */ - cp_parameter_declarator *parameters; + /* The parameters to the function as a TREE_LIST of decl/default. */ + tree parameters; /* The cv-qualifiers for the function. */ cp_cv_quals qualifiers; /* The exception-specification for the function. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c045353fe7f..3348d28425c 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -54,7 +54,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-flow.h" #include "pointer-set.h" -static tree grokparms (cp_parameter_declarator *, tree *); +static tree grokparms (tree parmlist, tree *); static const char *redeclaration_error_message (tree, tree); static int decl_jump_unsafe (tree); @@ -236,13 +236,7 @@ VEC(tree, gc) *deferred_mark_used_calls; with __attribute__((deprecated)). An object declared as __attribute__((deprecated)) suppresses warnings of uses of other deprecated items. */ - -enum deprecated_states { - DEPRECATED_NORMAL, - DEPRECATED_SUPPRESS -}; - -static enum deprecated_states deprecated_state = DEPRECATED_NORMAL; +enum deprecated_states deprecated_state = DEPRECATED_NORMAL; /* A TREE_LIST of VAR_DECLs. The TREE_PURPOSE is a RECORD_TYPE or @@ -9494,6 +9488,32 @@ check_default_argument (tree decl, tree arg) return arg; } +/* Returns a deprecated type used within TYPE, or NULL_TREE if none. */ + +static tree +type_is_deprecated (tree type) +{ + enum tree_code code; + if (TREE_DEPRECATED (type)) + return type; + if (TYPE_NAME (type) + && TREE_DEPRECATED (TYPE_NAME (type))) + return type; + + code = TREE_CODE (type); + + if (code == POINTER_TYPE || code == REFERENCE_TYPE + || code == OFFSET_TYPE || code == FUNCTION_TYPE + || code == METHOD_TYPE || code == ARRAY_TYPE) + return type_is_deprecated (TREE_TYPE (type)); + + if (TYPE_PTRMEMFUNC_P (type)) + return type_is_deprecated + (TREE_TYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type)))); + + return NULL_TREE; +} + /* Decode the list of parameter types for a function type. Given the list of things declared inside the parens, return a list of types. @@ -9504,41 +9524,31 @@ check_default_argument (tree decl, tree arg) *PARMS is set to the chain of PARM_DECLs created. */ static tree -grokparms (cp_parameter_declarator *first_parm, tree *parms) +grokparms (tree parmlist, tree *parms) { tree result = NULL_TREE; tree decls = NULL_TREE; - int ellipsis = !first_parm || first_parm->ellipsis_p; - cp_parameter_declarator *parm; + tree parm; int any_error = 0; - struct pointer_set_t *unique_decls = pointer_set_create (); - for (parm = first_parm; parm != NULL; parm = parm->next) + for (parm = parmlist; parm != NULL_TREE; parm = TREE_CHAIN (parm)) { tree type = NULL_TREE; - tree init = parm->default_argument; - tree attrs; - tree decl; + tree init = TREE_PURPOSE (parm); + tree decl = TREE_VALUE (parm); - if (parm == no_parameters) + if (parm == void_list_node) break; - attrs = parm->decl_specifiers.attributes; - parm->decl_specifiers.attributes = NULL_TREE; - decl = grokdeclarator (parm->declarator, &parm->decl_specifiers, - PARM, init != NULL_TREE, &attrs); if (! decl || TREE_TYPE (decl) == error_mark_node) continue; - if (attrs) - cplus_decl_attributes (&decl, attrs, 0); - type = TREE_TYPE (decl); if (VOID_TYPE_P (type)) { if (same_type_p (type, void_type_node) && DECL_SELF_REFERENCE_P (type) - && !DECL_NAME (decl) && !result && !parm->next && !ellipsis) + && !DECL_NAME (decl) && !result && TREE_CHAIN (parm) == void_list_node) /* this is a parmlist of `(void)', which is ok. */ break; cxx_incomplete_type_error (decl, type); @@ -9561,6 +9571,13 @@ grokparms (cp_parameter_declarator *first_parm, tree *parms) if (type != error_mark_node) { + if (deprecated_state != DEPRECATED_SUPPRESS) + { + tree deptype = type_is_deprecated (type); + if (deptype) + warn_deprecated_use (deptype); + } + /* Top-level qualifiers on the parameters are ignored for function types. */ type = cp_build_qualified_type (type, 0); @@ -9603,28 +9620,20 @@ grokparms (cp_parameter_declarator *first_parm, tree *parms) if (TREE_CODE (decl) == PARM_DECL && FUNCTION_PARAMETER_PACK_P (decl) - && parm->next) + && TREE_CHAIN (parm) + && TREE_CHAIN (parm) != void_list_node) error ("parameter packs must be at the end of the parameter list"); - if (DECL_NAME (decl)) - { - if (pointer_set_contains (unique_decls, DECL_NAME (decl))) - error ("multiple parameters named %qE", DECL_NAME (decl)); - else - pointer_set_insert (unique_decls, DECL_NAME (decl)); - } - TREE_CHAIN (decl) = decls; decls = decl; result = tree_cons (init, type, result); } decls = nreverse (decls); result = nreverse (result); - if (!ellipsis) + if (parm) result = chainon (result, void_list_node); *parms = decls; - pointer_set_destroy (unique_decls); return result; } diff --git a/gcc/cp/decl.h b/gcc/cp/decl.h index 52ab0fbaef5..ed287149d87 100644 --- a/gcc/cp/decl.h +++ b/gcc/cp/decl.h @@ -34,3 +34,16 @@ enum decl_context extern tree grokdeclarator (const cp_declarator *, const cp_decl_specifier_seq *, enum decl_context, int, tree*); + +/* States indicating how grokdeclarator() should handle declspecs marked + with __attribute__((deprecated)). An object declared as + __attribute__((deprecated)) suppresses warnings of uses of other + deprecated items. */ + +enum deprecated_states { + DEPRECATED_NORMAL, + DEPRECATED_SUPPRESS +}; + +extern enum deprecated_states deprecated_state; + diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index dea92b9c9ea..7b4c30344cc 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -2016,7 +2016,8 @@ write_template_args (tree args) ::= ::= L E # literal ::= L E # external name - ::= sr + ::= st # sizeof + ::= sr # dependent name ::= sr */ static void @@ -2042,6 +2043,12 @@ write_expression (tree expr) code = TREE_CODE (expr); } + if (code == OVERLOAD) + { + expr = OVL_FUNCTION (expr); + code = TREE_CODE (expr); + } + /* Handle pointers-to-members by making them look like expression nodes. */ if (code == PTRMEM_CST) @@ -2064,6 +2071,13 @@ write_expression (tree expr) else if (TREE_CODE_CLASS (code) == tcc_constant || (abi_version_at_least (2) && code == CONST_DECL)) write_template_arg_literal (expr); + else if (code == PARM_DECL) + { + /* A function parameter used under decltype in a late-specified + return type. Represented with a type placeholder. */ + write_string ("sT"); + write_type (non_reference (TREE_TYPE (expr))); + } else if (DECL_P (expr)) { /* G++ 3.2 incorrectly mangled non-type template arguments of @@ -2175,16 +2189,17 @@ write_expression (tree expr) switch (code) { case CALL_EXPR: - sorry ("call_expr cannot be mangled due to a defect in the C++ ABI"); + write_expression (CALL_EXPR_FN (expr)); + for (i = 0; i < call_expr_nargs (expr); ++i) + write_expression (CALL_EXPR_ARG (expr, i)); + write_char ('E'); break; case CAST_EXPR: write_type (TREE_TYPE (expr)); - /* There is no way to mangle a zero-operand cast like - "T()". */ if (!TREE_OPERAND (expr, 0)) - sorry ("zero-operand casts cannot be mangled due to a defect " - "in the C++ ABI"); + /* "T()" is mangled as "T(void)". */ + write_char ('v'); else write_expression (TREE_VALUE (TREE_OPERAND (expr, 0))); break; @@ -2195,7 +2210,6 @@ write_expression (tree expr) write_expression (TREE_OPERAND (expr, 0)); break; - /* Handle pointers-to-members specially. */ case SCOPE_REF: write_type (TREE_OPERAND (expr, 0)); diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 7fc6a9341ae..743f02365ee 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -604,6 +604,13 @@ pushdecl_maybe_friend (tree x, bool is_friend) scope of the current namespace, not the current function. */ && !(TREE_CODE (x) == VAR_DECL && DECL_EXTERNAL (x)) + /* When parsing the parameter list of a function declarator, + don't set DECL_CONTEXT to an enclosing function. When we + push the PARM_DECLs in order to process the function body, + current_binding_level->this_entity will be set. */ + && !(TREE_CODE (x) == PARM_DECL + && current_binding_level->kind == sk_function_parms + && current_binding_level->this_entity == NULL) && !DECL_CONTEXT (x)) DECL_CONTEXT (x) = current_function_decl; @@ -712,8 +719,6 @@ pushdecl_maybe_friend (tree x, bool is_friend) } else if (TREE_CODE (t) == PARM_DECL) { - gcc_assert (DECL_CONTEXT (t)); - /* Check for duplicate params. */ if (duplicate_decls (x, t, is_friend)) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t); @@ -4987,6 +4992,8 @@ pushtag (tree name, tree type, tag_scope scope) while (/* Cleanup scopes are not scopes from the point of view of the language. */ b->kind == sk_cleanup + /* Neither are function parameter scopes. */ + || b->kind == sk_function_parms /* Neither are the scopes used to hold template parameters for an explicit specialization. For an ordinary template declaration, these scopes are not scopes from the point of diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 3f6e3701127..88f92e7ccc4 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, tree); + (cp_declarator *, tree, cp_cv_quals, tree, tree); static cp_declarator *make_array_declarator (cp_declarator *, tree); static cp_declarator *make_pointer_declarator @@ -1013,7 +1013,7 @@ make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type, cp_declarator * make_call_declarator (cp_declarator *target, - cp_parameter_declarator *parms, + tree parms, cp_cv_quals cv_qualifiers, tree exception_specification, tree late_return_type) @@ -1736,9 +1736,9 @@ static tree cp_parser_type_id (cp_parser *); static void cp_parser_type_specifier_seq (cp_parser *, bool, cp_decl_specifier_seq *); -static cp_parameter_declarator *cp_parser_parameter_declaration_clause +static tree cp_parser_parameter_declaration_clause (cp_parser *); -static cp_parameter_declarator *cp_parser_parameter_declaration_list +static tree cp_parser_parameter_declaration_list (cp_parser *, bool *); static cp_parameter_declarator *cp_parser_parameter_declaration (cp_parser *, bool, bool *); @@ -12986,8 +12986,10 @@ cp_parser_direct_declarator (cp_parser* parser, if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED) { - cp_parameter_declarator *params; + tree params; unsigned saved_num_template_parameter_lists; + bool is_declarator = false; + tree t; /* In a member-declarator, the only valid interpretation of a parenthesis is the start of a @@ -13014,6 +13016,8 @@ cp_parser_direct_declarator (cp_parser* parser, = parser->num_template_parameter_lists; parser->num_template_parameter_lists = 0; + begin_scope (sk_function_parms, NULL_TREE); + /* Parse the parameter-declaration-clause. */ params = cp_parser_parameter_declaration_clause (parser); @@ -13028,6 +13032,8 @@ cp_parser_direct_declarator (cp_parser* parser, tree exception_specification; tree late_return; + is_declarator = true; + if (ctor_dtor_or_conv_p) *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0; first = false; @@ -13053,10 +13059,16 @@ cp_parser_direct_declarator (cp_parser* parser, return type, so are not those of the declared function. */ parser->default_arg_ok_p = false; - - /* Repeat the main loop. */ - continue; } + + /* Remove the function parms from scope. */ + for (t = current_binding_level->names; t; t = TREE_CHAIN (t)) + pop_binding (DECL_NAME (t), t); + leave_scope(); + + if (is_declarator) + /* Repeat the main loop. */ + continue; } /* If this is the first, we can try a parenthesized @@ -13728,10 +13740,10 @@ cp_parser_type_specifier_seq (cp_parser* parser, value of NULL indicates a parameter-declaration-clause consisting only of an ellipsis. */ -static cp_parameter_declarator * +static tree cp_parser_parameter_declaration_clause (cp_parser* parser) { - cp_parameter_declarator *parameters; + tree parameters; cp_token *token; bool ellipsis_p; bool is_error; @@ -13743,7 +13755,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) { /* Consume the `...' token. */ cp_lexer_consume_token (parser->lexer); - return NULL; + return NULL_TREE; } else if (token->type == CPP_CLOSE_PAREN) /* There are no parameters. */ @@ -13751,10 +13763,10 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) #ifndef NO_IMPLICIT_EXTERN_C if (in_system_header && current_class_type == NULL && current_lang_name == lang_name_c) - return NULL; + return NULL_TREE; else #endif - return no_parameters; + return void_list_node; } /* Check for `(void)', too, which is a special case. */ else if (token->keyword == RID_VOID @@ -13764,7 +13776,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) /* Consume the `void' token. */ cp_lexer_consume_token (parser->lexer); /* There are no parameters. */ - return no_parameters; + return void_list_node; } /* Parse the parameter-declaration-list. */ @@ -13799,8 +13811,8 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) ellipsis_p = false; /* Finish the parameter list. */ - if (parameters && ellipsis_p) - parameters->ellipsis_p = true; + if (!ellipsis_p) + parameters = chainon (parameters, void_list_node); return parameters; } @@ -13816,11 +13828,11 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) `void_list_node' is never appended to the list. Upon return, *IS_ERROR will be true iff an error occurred. */ -static cp_parameter_declarator * +static tree cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) { - cp_parameter_declarator *parameters = NULL; - cp_parameter_declarator **tail = ¶meters; + tree parameters = NULL_TREE; + tree *tail = ¶meters; bool saved_in_unbraced_linkage_specification_p; /* Assume all will go well. */ @@ -13836,6 +13848,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) while (true) { cp_parameter_declarator *parameter; + tree decl = error_mark_node; bool parenthesized_p; /* Parse the parameter. */ parameter @@ -13843,17 +13856,38 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) /*template_parm_p=*/false, &parenthesized_p); + /* We don't know yet if the enclosing context is deprecated, so wait + and warn in grokparms if appropriate. */ + deprecated_state = DEPRECATED_SUPPRESS; + + if (parameter) + decl = grokdeclarator (parameter->declarator, + ¶meter->decl_specifiers, + PARM, + parameter->default_argument != NULL_TREE, + ¶meter->decl_specifiers.attributes); + + deprecated_state = DEPRECATED_NORMAL; + /* If a parse error occurred parsing the parameter declaration, then the entire parameter-declaration-list is erroneous. */ - if (!parameter) + if (decl == error_mark_node) { *is_error = true; - parameters = NULL; + parameters = error_mark_node; break; } + + if (parameter->decl_specifiers.attributes) + cplus_decl_attributes (&decl, + parameter->decl_specifiers.attributes, + 0); + if (DECL_NAME (decl)) + decl = pushdecl (decl); + /* Add the new parameter to the list. */ - *tail = parameter; - tail = ¶meter->next; + *tail = build_tree_list (parameter->default_argument, decl); + tail = &TREE_CHAIN (*tail); /* Peek at the next token. */ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7c9165c20ea..4aa7b1ad146 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -9556,11 +9556,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) { tree type; - type = - finish_decltype_type (tsubst_expr - (DECLTYPE_TYPE_EXPR (t), args, - complain, in_decl, - /*integral_constant_expression_p=*/false), + ++skip_evaluation; + + type = tsubst_expr (DECLTYPE_TYPE_EXPR (t), args, + complain, in_decl, + /*integral_constant_expression_p=*/false); + + --skip_evaluation; + + type = + finish_decltype_type (type, DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t)); return cp_build_qualified_type_real (type, cp_type_quals (t) @@ -9796,7 +9801,22 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) { case PARM_DECL: r = retrieve_local_specialization (t); - gcc_assert (r != NULL); + + if (r == NULL) + { + /* This can happen for a parameter name used later in a function + declaration (such as in a late-specified return type). + Replace it with an arbitrary expression with the same type + (*(T*)0). This should only occur in an unevaluated context + (i.e. decltype). */ + gcc_assert (skip_evaluation && DECL_CONTEXT (t) == NULL_TREE); + r = non_reference (TREE_TYPE (t)); + r = tsubst (r, args, complain, in_decl); + r = build_pointer_type (r); + r = build_c_cast (r, null_node); + return cp_build_indirect_ref (r, NULL, tf_warning_or_error); + } + if (TREE_CODE (r) == ARGUMENT_PACK_SELECT) r = ARGUMENT_PACK_SELECT_ARG (r); mark_used (r); diff --git a/gcc/testsuite/g++.dg/cpp0x/auto2.C b/gcc/testsuite/g++.dg/cpp0x/auto2.C index a3df9d1927e..626e9e245d4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto2.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto2.C @@ -69,4 +69,6 @@ int main() case 42: break; } + + auto j = 42, k = 24; } diff --git a/gcc/testsuite/g++.dg/cpp0x/auto3.C b/gcc/testsuite/g++.dg/cpp0x/auto3.C index dc4218bf023..769d987c961 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto3.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto3.C @@ -5,6 +5,10 @@ auto x; // { dg-error "auto" } +// If the type deduced for the template parameter U is not the same in each +// deduction, the program is ill-formed. +auto i = 42, j = 42.0; // { dg-error "" "" { xfail *-*-* } } + // New CWG issue auto a[2] = { 1, 2 }; // { dg-error "auto" } diff --git a/gcc/testsuite/g++.dg/cpp0x/auto6.C b/gcc/testsuite/g++.dg/cpp0x/auto6.C index ac209934869..a574f54758f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto6.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto6.C @@ -6,4 +6,20 @@ auto f() -> int } template -auto add(T t, U u) -> decltype (t+u); // { dg-bogus "not declared" "" { xfail *-*-* } } +auto add(T t, U u) -> decltype (t+u); + +template +decltype(T()+U()) add2(T t, U u); + +template +U g (T, U); + +template +auto add3(T t, U u) -> decltype (g(t,u)); + +int main() +{ + auto i = add(1, 2.0); + auto i2 = add2(1, 2.0); + auto i3 = add3(1, 2.0); +} diff --git a/gcc/testsuite/g++.dg/other/error15.C b/gcc/testsuite/g++.dg/other/error15.C index 0a5bae1b3c0..3601852322a 100644 --- a/gcc/testsuite/g++.dg/other/error15.C +++ b/gcc/testsuite/g++.dg/other/error15.C @@ -3,58 +3,54 @@ extern void g0 (int a, int b); extern void g1 (int a, float b); -extern void f0 (int a, - int a); // { dg-error "multiple parameters named 'a'" } -extern void f1 (int a, - float a); // { dg-error "multiple parameters named 'a'" } -extern void f3 (int a, int b, int c, - int a); // { dg-error "multiple parameters named 'a'" } -extern void f4 (int a, int b, int c, - int a, - int a); // { dg-error "multiple parameters named 'a'" } -extern void f5 (int a, int b, int c, int d, int e, int f, int g, int h, - int a, +extern void f0 (int a, // { dg-error "previous" } + int a); // { dg-error "redefinition" } +extern void f1 (int a, // { dg-error "previous" } + float a); // { dg-error "conflicting" } +extern void f3 (int a, int b, int c, // { dg-error "previous" } + int a); // { dg-error "redefinition" } +extern void f4 (int a, int b, int c, // { dg-error "previous" } + int a, // { dg-error "redefinition" } + int a); // { dg-error "redefinition" } +extern void f5 (int a, int b, int c, int d, int e, int f, int g, int h, // { dg-error "previous" } + int a, // { dg-error "redefinition" } int i, int j, int k, int l, int m, int n, int o, int p, int q, int r, int s, int t, int u, int v, int w, int x, int y, - int z); // { dg-error "multiple parameters named 'a'" } + int z); -extern void f6 (int a, int, int, int, int, int, int, int, int, int, int, - int a, +extern void f6 (int a, int, int, int, int, int, int, int, int, int, int, // { dg-error "previous" } + int a, // { dg-error "redefinition" } int, int, int, int, int, int, int, int, int, int, int, float, float, float, float, float, float, float, float, - int); // { dg-error "multiple parameters named 'a'" } + int); -extern void f7 (void (*a)(int), - void (*a)(int)); // { dg-error "multiple parameters named 'a'" } -extern void f8 (float (*a)(int), - int (*a)(float)); // { dg-error "multiple parameters named 'a'" } +extern void f7 (void (*a)(int), // { dg-error "previous" } + void (*a)(int)); // { dg-error "redefinition" } +extern void f8 (float (*a)(int), // { dg-error "previous" } + int (*a)(float)); // { dg-error "conflicting" } -extern void f9 (int a, - int a, - int a); -// { dg-error "multiple parameters named 'a'" "" { target *-*-* } 34 } +extern void f9 (int a, // { dg-error "previous" } + int a, // { dg-error "redefinition" } + int a); // { dg-error "redefinition" } -extern void f10 (int a, - int b, - int c, - int c, - int b, - int a); -// { dg-error "multiple parameters named 'a'" "" { target *-*-* } 42 } -// { dg-error "multiple parameters named 'b'" "" { target *-*-* } 42 } -// { dg-error "multiple parameters named 'c'" "" { target *-*-* } 42 } +extern void f10 (int a, // { dg-error "previous" } + int b, // { dg-error "previous" } + int c, // { dg-error "previous" } + int c, // { dg-error "redefinition" } + int b, // { dg-error "redefinition" } + int a); // { dg-error "redefinition" } class C1 { public: void C1_g0 (int a, int b); - void C1_f0 (int a, - int a); // { dg-error "multiple parameters named 'a'" } + void C1_f0 (int a, // { dg-error "previous" } + int a); // { dg-error "redefinition" } }; template class C2 { public: void C2_g0 (T a, T b); - void C2_f0 (T a, - T a); // { dg-error "multiple parameters named 'a'" } + void C2_f0 (T a, // { dg-error "previous" } + T a); // { dg-error "redefinition" } }; diff --git a/gcc/testsuite/g++.dg/other/error6.C b/gcc/testsuite/g++.dg/other/error6.C index 9b403c7207b..21180d765ab 100644 --- a/gcc/testsuite/g++.dg/other/error6.C +++ b/gcc/testsuite/g++.dg/other/error6.C @@ -1,6 +1,7 @@ // { dg-do compile } // Make sure we emit a decent error message when trying to mangle an // expression not supported by the C++ ABI due to a defect. +// Update: Better to make it supported, I think... template struct A {}; @@ -15,5 +16,5 @@ A func(void); int main() { - func(); // { dg-error "sorry, unimplemented" } + func(); } diff --git a/gcc/testsuite/g++.dg/other/pr28114.C b/gcc/testsuite/g++.dg/other/pr28114.C index e16f6b589e5..e370f717c3a 100644 --- a/gcc/testsuite/g++.dg/other/pr28114.C +++ b/gcc/testsuite/g++.dg/other/pr28114.C @@ -5,5 +5,5 @@ template void foo(struct {}*); // { dg-error "" } void bar() { - foo<0>(0); + foo<0>(0); // { dg-error "" } } diff --git a/gcc/testsuite/g++.dg/parse/error3.C b/gcc/testsuite/g++.dg/parse/error3.C index 1f337e91cde..2856850fb76 100644 --- a/gcc/testsuite/g++.dg/parse/error3.C +++ b/gcc/testsuite/g++.dg/parse/error3.C @@ -6,14 +6,4 @@ static void InstantiateConstraint(const float&, unsigned, char*, char*, unsigned*)); // { dg-error "64: error: expected ',' or '...' before '&' token" "" { target *-*-* } { 5 } } - -/// in the coming test, the column information is broken as it points to -// the end of the declaration instead of pointing to the begining of the -// 'TYPE' identifier. This is due to the warning being generated by the -// declaration groking code (gcc/cp/decl.c) and not the parser. So in that -// code, the exact token location information is lost as the declaration -// groking code manipulates TREEs only. The token location used is then -// the global one that is not accurate enough. Anyway, let's say it is -// good enough for now, until we find a way to propagate token location to -// code paths that manipulate TREEs only. -// { dg-error "64: error: ISO C\\+\\+ forbids declaration of 'TYPE' with no type" "" { target *-*-* } { 7 } } +// { dg-error "60: error: ISO C\\+\\+ forbids declaration of 'TYPE' with no type" "" { target *-*-* } { 5 } } diff --git a/gcc/testsuite/g++.old-deja/g++.jason/rfg16.C b/gcc/testsuite/g++.old-deja/g++.jason/rfg16.C index 6a39ff42e3d..d42516d4fcf 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/rfg16.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/rfg16.C @@ -1,5 +1,5 @@ // { dg-do assemble } // Bug: g++ doesn't push parameter decls as they are parsed. -void (*ptr) (int foo, int array[sizeof(foo)]); // { dg-bogus "" "" { xfail *-*-* } } -void test2 (int bar, int array[sizeof(bar)]) { } // { dg-bogus "" "" { xfail *-*-* } } +void (*ptr) (int foo, int array[sizeof(foo)]); +void test2 (int bar, int array[sizeof(bar)]) { } diff --git a/gcc/testsuite/g++.old-deja/g++.oliva/template1.C b/gcc/testsuite/g++.old-deja/g++.oliva/template1.C index 133899e55e8..8ac05146866 100644 --- a/gcc/testsuite/g++.old-deja/g++.oliva/template1.C +++ b/gcc/testsuite/g++.old-deja/g++.oliva/template1.C @@ -11,5 +11,5 @@ template struct foo { }; void bar() { - foo<>::bar(0); // { dg-error "" "" } instantiated from here + foo<>::bar(0); } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp29.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp29.C index c14ca235772..808f233c648 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/memtemp29.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp29.C @@ -9,7 +9,7 @@ struct S void f(U u); template - void g(U U); + void g(U u); int c[16]; };