diff options
-rw-r--r-- | gcc/cp/ChangeLog | 32 | ||||
-rw-r--r-- | gcc/cp/class.c | 8 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/decl.c | 69 | ||||
-rw-r--r-- | gcc/cp/friend.c | 2 | ||||
-rw-r--r-- | gcc/cp/parser.c | 30 | ||||
-rw-r--r-- | gcc/cp/tree.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/ctor3.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/dtor6.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/error29.C | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/operator6.C | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/class3.C | 2 |
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" } |