re PR c++/25635 (Bogus cruft in error message for invalid operator declaration)

PR c++/25635
	* class.c (add_method): Set TYPE_HAS_CONVERSION for classes with a
	conversion operator.
	* decl.c (grokdeclarator): Do not set TYPE_HAS_CONVERSION here.
	PR c++/25638
	* class.c (add_method): Never associate more than one destructor
	with a single class.
	PR c++/25637
	* cp-tree.h (do_friend): Adjust prototype.
	* decl.c (grokfndecl): Make funcdef_flag a bool, not an int.
	(grokdeclarator): Likewise.  Refine check for invalid
	declarations/definitions of member functions outside of their own
	class.
	* friend.c (do_friend): Make funcdef_flag a bool, not an int.
	PR c++/25633
	* parser.c (cp_parser_mem_initializer_list): Check result of
	cp_parser_mem_initializer against error_mark_node, not NULL_TREE.
	(cp_parser_mem_initializer): Return error_mark_node for failure.
	PR c++/25634
	* parser.c (cp_parser_template_parameter_list): Call
	begin_template_parm_list and end_template_parm_list here.
	(cp_parser_type_parameter): Not here.
	(cp_parser_template_declaration_after_export): Or here.
	(cp_parser_elaborated_type_specifier): Call
	cp_parser_check_template_parameters.
	* tree.c (build_target_expr_with_type): Use force_target_expr.
	PR c++/25635
	* g++.dg/parse/operator6.C: New test.
	PR c++/25637
	* g++.dg/parse/error29.C: New test.
	PR c++/25638
	* g++.dg/parse/dtor6.C: New test.
	PR c++/25633
	* g++.dg/parse/ctor3.C: New test.
	PR c++/25634
	* g++.dg/template/class3.C: New test.

From-SVN: r109270
This commit is contained in:
Mark Mitchell 2006-01-03 08:41:21 +00:00 committed by Mark Mitchell
parent 622d525826
commit 357d956ebd
13 changed files with 145 additions and 55 deletions

View File

@ -1,5 +1,37 @@
2006-01-02 Mark Mitchell <mark@codesourcery.com>
PR c++/25635
* class.c (add_method): Set TYPE_HAS_CONVERSION for classes with a
conversion operator.
* decl.c (grokdeclarator): Do not set TYPE_HAS_CONVERSION here.
PR c++/25638
* class.c (add_method): Never associate more than one destructor
with a single class.
PR c++/25637
* cp-tree.h (do_friend): Adjust prototype.
* decl.c (grokfndecl): Make funcdef_flag a bool, not an int.
(grokdeclarator): Likewise. Refine check for invalid
declarations/definitions of member functions outside of their own
class.
* friend.c (do_friend): Make funcdef_flag a bool, not an int.
PR c++/25633
* parser.c (cp_parser_mem_initializer_list): Check result of
cp_parser_mem_initializer against error_mark_node, not NULL_TREE.
(cp_parser_mem_initializer): Return error_mark_node for failure.
PR c++/25634
* parser.c (cp_parser_template_parameter_list): Call
begin_template_parm_list and end_template_parm_list here.
(cp_parser_type_parameter): Not here.
(cp_parser_template_declaration_after_export): Or here.
(cp_parser_elaborated_type_specifier): Call
cp_parser_check_template_parameters.
* tree.c (build_target_expr_with_type): Use force_target_expr.
* decl2.c (mark_used): Fix typo in comment.
2006-01-02 Volker Reichelt <reichelt@igpm.rwth-aachen.de>

View File

@ -1059,10 +1059,16 @@ add_method (tree type, tree method, tree using_decl)
}
}
/* A class should never have more than one destructor. */
if (current_fns && DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
return false;
/* Add the new binding. */
overload = build_overload (method, current_fns);
if (!conv_p && slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && !complete_p)
if (conv_p)
TYPE_HAS_CONVERSION (type) = 1;
else if (slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && !complete_p)
push_class_level_binding (DECL_NAME (method), overload);
if (insert_p)

View File

@ -3935,7 +3935,7 @@ extern tree cplus_expand_constant (tree);
extern int is_friend (tree, tree);
extern void make_friend_class (tree, tree, bool);
extern void add_friend (tree, tree, bool);
extern tree do_friend (tree, tree, tree, tree, enum overload_flags, cp_cv_quals, int);
extern tree do_friend (tree, tree, tree, tree, enum overload_flags, cp_cv_quals, bool);
/* in init.c */
extern tree expand_member_init (tree);

View File

@ -5697,7 +5697,7 @@ grokfndecl (tree ctype,
int publicp,
int inlinep,
special_function_kind sfk,
int funcdef_flag,
bool funcdef_flag,
int template_count,
tree in_namespace,
tree* attrlist)
@ -5918,7 +5918,7 @@ grokfndecl (tree ctype,
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
2 * (funcdef_flag != 0) +
2 * funcdef_flag +
4 * (friendp != 0));
if (decl == error_mark_node)
return NULL_TREE;
@ -5940,27 +5940,26 @@ grokfndecl (tree ctype,
> template_class_depth (ctype))
? current_template_parms
: NULL_TREE);
if (old_decl && TREE_CODE (old_decl) == TEMPLATE_DECL)
/* Because grokfndecl is always supposed to return a
FUNCTION_DECL, we pull out the DECL_TEMPLATE_RESULT
here. We depend on our callers to figure out that its
really a template that's being returned. */
old_decl = DECL_TEMPLATE_RESULT (old_decl);
if (old_decl && DECL_STATIC_FUNCTION_P (old_decl)
&& TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
/* Remove the `this' parm added by grokclassfn.
XXX Isn't this done in start_function, too? */
revert_static_member_fn (decl);
if (old_decl && DECL_ARTIFICIAL (old_decl))
error ("definition of implicitly-declared %qD", old_decl);
if (old_decl)
{
tree ok;
tree pushed_scope;
if (TREE_CODE (old_decl) == TEMPLATE_DECL)
/* Because grokfndecl is always supposed to return a
FUNCTION_DECL, we pull out the DECL_TEMPLATE_RESULT
here. We depend on our callers to figure out that its
really a template that's being returned. */
old_decl = DECL_TEMPLATE_RESULT (old_decl);
if (DECL_STATIC_FUNCTION_P (old_decl)
&& TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
/* Remove the `this' parm added by grokclassfn.
XXX Isn't this done in start_function, too? */
revert_static_member_fn (decl);
if (DECL_ARTIFICIAL (old_decl))
error ("definition of implicitly-declared %qD", old_decl);
/* Since we've smashed OLD_DECL to its
DECL_TEMPLATE_RESULT, we must do the same to DECL. */
if (TREE_CODE (decl) == TEMPLATE_DECL)
@ -6627,7 +6626,8 @@ grokdeclarator (const cp_declarator *declarator,
tree typedef_decl = NULL_TREE;
const char *name = NULL;
tree typedef_type = NULL_TREE;
int funcdef_flag = 0;
/* True if this declarator is a function definition. */
bool funcdef_flag = false;
cp_declarator_kind innermost_code = cdk_error;
int bitfield = 0;
#if 0
@ -6674,9 +6674,9 @@ grokdeclarator (const cp_declarator *declarator,
thread_p = declspecs->specs[(int)ds_thread];
if (decl_context == FUNCDEF)
funcdef_flag = 1, decl_context = NORMAL;
funcdef_flag = true, decl_context = NORMAL;
else if (decl_context == MEMFUNCDEF)
funcdef_flag = -1, decl_context = FIELD;
funcdef_flag = true, decl_context = FIELD;
else if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
@ -7349,8 +7349,6 @@ grokdeclarator (const cp_declarator *declarator,
&& (friendp == 0 || dname == current_class_name))
ctype = current_class_type;
if (ctype && sfk == sfk_conversion)
TYPE_HAS_CONVERSION (ctype) = 1;
if (ctype && (sfk == sfk_constructor
|| sfk == sfk_destructor))
{
@ -7604,22 +7602,25 @@ grokdeclarator (const cp_declarator *declarator,
{
tree sname = declarator->u.id.unqualified_name;
if (current_class_type
&& (!friendp || funcdef_flag))
{
error (funcdef_flag
? "cannot define member function %<%T::%s%> within %<%T%>"
: "cannot declare member function %<%T::%s%> within %<%T%>",
ctype, name, current_class_type);
return error_mark_node;
}
if (TREE_CODE (sname) == IDENTIFIER_NODE
&& NEW_DELETE_OPNAME_P (sname))
/* Overloaded operator new and operator delete
are always static functions. */
;
else if (current_class_type == NULL_TREE || friendp)
type
= build_method_type_directly (ctype,
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
else
{
error ("cannot declare member function %<%T::%s%> within %<%T%>",
ctype, name, current_class_type);
return error_mark_node;
}
type = build_method_type_directly (ctype,
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
}
else if (declspecs->specs[(int)ds_typedef]
|| COMPLETE_TYPE_P (complete_type (ctype)))
@ -8179,7 +8180,7 @@ grokdeclarator (const cp_declarator *declarator,
{
decl = check_explicit_specialization
(unqualified_id, decl, template_count,
2 * (funcdef_flag != 0) + 4);
2 * funcdef_flag + 4);
if (decl == error_mark_node)
return error_mark_node;
}

View File

@ -408,7 +408,7 @@ tree
do_friend (tree ctype, tree declarator, tree decl,
tree attrlist, enum overload_flags flags,
cp_cv_quals quals,
int funcdef_flag)
bool funcdef_flag)
{
/* Every decl that gets here is a friend of something. */
DECL_FRIEND_P (decl) = 1;

View File

@ -7808,7 +7808,7 @@ cp_parser_mem_initializer_list (cp_parser* parser)
/* Parse the mem-initializer. */
mem_initializer = cp_parser_mem_initializer (parser);
/* Add it to the list, unless it was erroneous. */
if (mem_initializer)
if (mem_initializer != error_mark_node)
{
TREE_CHAIN (mem_initializer) = mem_initializer_list;
mem_initializer_list = mem_initializer;
@ -7837,7 +7837,8 @@ cp_parser_mem_initializer_list (cp_parser* parser)
Returns a TREE_LIST. The TREE_PURPOSE is the TYPE (for a base
class) or FIELD_DECL (for a non-static data member) to initialize;
the TREE_VALUE is the expression-list. */
the TREE_VALUE is the expression-list. An empty initialization
list is represented by void_list_node. */
static tree
cp_parser_mem_initializer (cp_parser* parser)
@ -7862,12 +7863,14 @@ cp_parser_mem_initializer (cp_parser* parser)
= cp_parser_parenthesized_expression_list (parser, false,
/*cast_p=*/false,
/*non_constant_p=*/NULL);
if (expression_list == error_mark_node)
return error_mark_node;
if (!expression_list)
expression_list = void_type_node;
in_base_initializer = 0;
return member ? build_tree_list (member, expression_list) : NULL_TREE;
return member ? build_tree_list (member, expression_list) : error_mark_node;
}
/* Parse a mem-initializer-id.
@ -8277,6 +8280,7 @@ cp_parser_template_parameter_list (cp_parser* parser)
{
tree parameter_list = NULL_TREE;
begin_template_parm_list ();
while (true)
{
tree parameter;
@ -8299,7 +8303,7 @@ cp_parser_template_parameter_list (cp_parser* parser)
cp_lexer_consume_token (parser->lexer);
}
return parameter_list;
return end_template_parm_list (parameter_list);
}
/* Parse a template-parameter.
@ -8447,10 +8451,7 @@ cp_parser_type_parameter (cp_parser* parser)
/* Look for the `<'. */
cp_parser_require (parser, CPP_LESS, "`<'");
/* Parse the template-parameter-list. */
begin_template_parm_list ();
parameter_list
= cp_parser_template_parameter_list (parser);
parameter_list = end_template_parm_list (parameter_list);
parameter_list = cp_parser_template_parameter_list (parser);
/* Look for the `>'. */
cp_parser_require (parser, CPP_GREATER, "`>'");
/* Look for the `class' keyword. */
@ -10112,6 +10113,11 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
(parser->num_template_parameter_lists
&& (cp_parser_next_token_starts_class_definition_p (parser)
|| cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)));
/* An unqualified name was used to reference this type, so
there were no qualifying templates. */
if (!cp_parser_check_template_parameters (parser,
/*num_templates=*/0))
return error_mark_node;
type = xref_tag (tag_type, identifier, ts, template_p);
}
}
@ -15259,12 +15265,8 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
parameter_list = NULL_TREE;
}
else
{
/* Parse the template parameters. */
begin_template_parm_list ();
parameter_list = cp_parser_template_parameter_list (parser);
parameter_list = end_template_parm_list (parameter_list);
}
/* Parse the template parameters. */
parameter_list = cp_parser_template_parameter_list (parser);
/* Look for the `>'. */
cp_parser_skip_until_found (parser, CPP_GREATER, "`>'");

View File

@ -325,8 +325,6 @@ build_cplus_new (tree type, tree init)
tree
build_target_expr_with_type (tree init, tree type)
{
tree slot;
gcc_assert (!VOID_TYPE_P (type));
if (TREE_CODE (init) == TARGET_EXPR)
@ -342,8 +340,7 @@ build_target_expr_with_type (tree init, tree type)
aggregate; there's no additional work to be done. */
return force_rvalue (init);
slot = build_local_temp (type);
return build_target_expr (slot, init);
return force_target_expr (type, init);
}
/* Like the above function, but without the checking. This function should

View File

@ -1,3 +1,20 @@
2006-01-02 Mark Mitchell <mark@codesourcery.com>
PR c++/25635
* g++.dg/parse/operator6.C: New test.
PR c++/25637
* g++.dg/parse/error29.C: New test.
PR c++/25638
* g++.dg/parse/dtor6.C: New test.
PR c++/25633
* g++.dg/parse/ctor3.C: New test.
PR c++/25634
* g++.dg/template/class3.C: New test.
2006-01-02 Geoffrey Keating <geoffk@apple.com>
* g++.dg/debug/debug9.C: New.

View File

@ -0,0 +1,8 @@
// PR c++/25633
struct A {};
struct B : A
{
B() : A {} // { dg-error "expected" }
};

View File

@ -0,0 +1,8 @@
// PR c++/25638
struct A { ~A(); }; // { dg-error "candidate" }
struct B : A
{
template<int> friend A::~A(); // { dg-error "match" }
};

View File

@ -0,0 +1,12 @@
// PR c++/25637
struct A {
void foo();
A();
void operator delete(void *);
};
struct B {
friend void A::foo() {} // { dg-error "define" }
friend void A::operator delete(void*) {} // { dg-error "define" }
friend A::A() {} // { dg-error "define" }
};

View File

@ -0,0 +1,5 @@
// PR c++/25635
struct A {};
A::operator int(); // { dg-error "class" }

View File

@ -0,0 +1,2 @@
// PR c++/25634
template<int> template<int> struct A; // { dg-error "too many" }