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
This commit is contained in:
Jason Merrill 2008-09-08 16:52:44 -04:00 committed by Jason Merrill
parent 37022b7c72
commit b344d949d2
18 changed files with 260 additions and 130 deletions

View File

@ -1,3 +1,27 @@
2008-09-06 Jason Merrill <jason@redhat.com>
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 <doug.gregor@gmail.com>
PR c++/37342

View File

@ -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. */

View File

@ -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;
}

View File

@ -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;

View File

@ -2016,7 +2016,8 @@ write_template_args (tree args)
<expr-primary> ::= <template-param>
::= L <type> <value number> E # literal
::= L <mangled-name> E # external name
::= sr <type> <unqualified-name>
::= st <type> # sizeof
::= sr <type> <unqualified-name> # dependent name
::= sr <type> <unqualified-name> <template-args> */
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));

View File

@ -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

View 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, 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 = &parameters;
tree parameters = NULL_TREE;
tree *tail = &parameters;
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,
&parameter->decl_specifiers,
PARM,
parameter->default_argument != NULL_TREE,
&parameter->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 = &parameter->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)

View File

@ -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);

View File

@ -69,4 +69,6 @@ int main()
case 42:
break;
}
auto j = 42, k = 24;
}

View File

@ -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" }

View File

@ -6,4 +6,20 @@ auto f() -> int
}
template<class T, class U>
auto add(T t, U u) -> decltype (t+u); // { dg-bogus "not declared" "" { xfail *-*-* } }
auto add(T t, U u) -> decltype (t+u);
template<class T, class U>
decltype(T()+U()) add2(T t, U u);
template <class T, class U>
U g (T, U);
template<class T, class U>
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);
}

View File

@ -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 T>
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" }
};

View File

@ -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 <int N>
struct A {};
@ -15,5 +16,5 @@ A<sizeof(T::foo())> func(void);
int main()
{
func<B>(); // { dg-error "sorry, unimplemented" }
func<B>();
}

View File

@ -5,5 +5,5 @@ template<int> void foo(struct {}*); // { dg-error "" }
void bar()
{
foo<0>(0);
foo<0>(0); // { dg-error "" }
}

View File

@ -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 } }

View File

@ -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)]) { }

View File

@ -11,5 +11,5 @@ template<int P = 0> struct foo {
};
void bar() {
foo<>::bar(0); // { dg-error "" "" } instantiated from here
foo<>::bar(0);
}

View File

@ -9,7 +9,7 @@ struct S
void f(U u);
template <class U>
void g(U U);
void g(U u);
int c[16];
};