aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog32
-rw-r--r--gcc/cp/class.c8
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c69
-rw-r--r--gcc/cp/friend.c2
-rw-r--r--gcc/cp/parser.c30
-rw-r--r--gcc/cp/tree.c5
-rw-r--r--gcc/testsuite/ChangeLog17
-rw-r--r--gcc/testsuite/g++.dg/parse/ctor3.C8
-rw-r--r--gcc/testsuite/g++.dg/parse/dtor6.C8
-rw-r--r--gcc/testsuite/g++.dg/parse/error29.C12
-rw-r--r--gcc/testsuite/g++.dg/parse/operator6.C5
-rw-r--r--gcc/testsuite/g++.dg/template/class3.C2
13 files changed, 145 insertions, 55 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a964986..4c03812 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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>
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 2ccc724..4509ac2 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3ac322d..3fbaff8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index d6074d7..020d96f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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;
}
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index c71b90f..0ae9130 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -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;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 90d1486..bfcf261 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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, "`>'");
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 9575c49..df59f50 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a09d804..f96ba05 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.dg/parse/ctor3.C b/gcc/testsuite/g++.dg/parse/ctor3.C
new file mode 100644
index 0000000..193ffae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/ctor3.C
@@ -0,0 +1,8 @@
+// PR c++/25633
+
+struct A {};
+
+struct B : A
+{
+ B() : A {} // { dg-error "expected" }
+};
diff --git a/gcc/testsuite/g++.dg/parse/dtor6.C b/gcc/testsuite/g++.dg/parse/dtor6.C
new file mode 100644
index 0000000..3333161
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/dtor6.C
@@ -0,0 +1,8 @@
+// PR c++/25638
+
+struct A { ~A(); }; // { dg-error "candidate" }
+
+struct B : A
+{
+ template<int> friend A::~A(); // { dg-error "match" }
+};
diff --git a/gcc/testsuite/g++.dg/parse/error29.C b/gcc/testsuite/g++.dg/parse/error29.C
new file mode 100644
index 0000000..b50b275
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error29.C
@@ -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" }
+};
diff --git a/gcc/testsuite/g++.dg/parse/operator6.C b/gcc/testsuite/g++.dg/parse/operator6.C
new file mode 100644
index 0000000..e58a3a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/operator6.C
@@ -0,0 +1,5 @@
+// PR c++/25635
+
+struct A {};
+
+A::operator int(); // { dg-error "class" }
diff --git a/gcc/testsuite/g++.dg/template/class3.C b/gcc/testsuite/g++.dg/template/class3.C
new file mode 100644
index 0000000..44a02a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/class3.C
@@ -0,0 +1,2 @@
+// PR c++/25634
+template<int> template<int> struct A; // { dg-error "too many" }