From 4546865e5b18963ce661d5053a6b4b7b15adfe7d Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sat, 20 Mar 2004 00:18:24 +0000 Subject: [PATCH] call.c (build_op_delete_call): Do not forget the placement arguments when iterating through mutiple delete... * call.c (build_op_delete_call): Do not forget the placement arguments when iterating through mutiple delete operators. * cp-tree.h (svaed_scope): Remove last_parms. (NEW_DELETE_OPNAME_P): New macro. (last_function_parms): Remove. (do_friend): Adjust prototype. * decl.c (grokparms): Return the PARM_DECLs directly, rather than using last_function_parms. (grokfndecl): Take the PARM_DECLs as an argument, rather than using last_function_parms. (grokdeclarator): Adjust accordingly. Do not form METHOD_TYPEs for class-specific operator new and operator delete. (grok_op_properties): Do not look for allocation functions with METHOD_TYPEs. (start_function): Use DECL_ARGUMENTS instead of last_function_parms. * decl.h (last_function_parms): Do not declare. * decl2.c (grokclassfn): Do not use last_function_parms. * friend.c (do_friend): Remove parmdecls parameter. * name-lookup.c (push_to_top_level): Do not save last_function_parms. (pop_from_top_level): Do not restore it. * pt.c (check_explicit_specialization): Do not adjust last_function_parms. * name-lookup.c (do_local_using_decl): Create a local binding for types brought in via using declarations. * name-lookup.c (lookup_arg_dependent): Handle block-scope function declarations correctly. * semantics.c (finish_id_expression): Correct handling of conversion operators to dependent types. * typeck.c (lookup_destructor): Allow the use of destructors from base classes. * g++.dg/init/placement3.C: New test. * g++.dg/template/spec13.C: New test. * g++.dg/lookup/using11.C: New test. * g++.dg/lookup/koenig3.C: New test. * g++.dg/template/operator2.C: New test. * g++.dg/expr/dtor3.C: New test. * g++.old-deja/g++.brendan/crash15.C: Remove incorrect dg-error marker. * g++.old-deja/g++.law/visibility28.C: Likewise. From-SVN: r79722 --- gcc/cp/ChangeLog | 39 ++++++++++ gcc/cp/call.c | 10 +-- gcc/cp/cp-tree.h | 12 ++- gcc/cp/decl.c | 77 ++++++++----------- gcc/cp/decl.h | 4 - gcc/cp/decl2.c | 5 +- gcc/cp/friend.c | 7 +- gcc/cp/name-lookup.c | 15 ++-- gcc/cp/pt.c | 9 +-- gcc/cp/semantics.c | 15 +++- gcc/cp/typeck.c | 10 ++- gcc/testsuite/ChangeLog | 17 ++++ gcc/testsuite/g++.dg/expr/dtor3.C | 10 +++ gcc/testsuite/g++.dg/init/placement3.C | 30 ++++++++ gcc/testsuite/g++.dg/lookup/koenig3.C | 13 ++++ gcc/testsuite/g++.dg/lookup/using11.C | 9 +++ gcc/testsuite/g++.dg/template/operator2.C | 8 ++ gcc/testsuite/g++.dg/template/spec13.C | 16 ++++ .../g++.old-deja/g++.brendan/crash15.C | 2 +- .../g++.old-deja/g++.law/visibility28.C | 2 +- 20 files changed, 222 insertions(+), 88 deletions(-) create mode 100644 gcc/testsuite/g++.dg/expr/dtor3.C create mode 100644 gcc/testsuite/g++.dg/init/placement3.C create mode 100644 gcc/testsuite/g++.dg/lookup/koenig3.C create mode 100644 gcc/testsuite/g++.dg/lookup/using11.C create mode 100644 gcc/testsuite/g++.dg/template/operator2.C create mode 100644 gcc/testsuite/g++.dg/template/spec13.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7c8c1d26412..654e6a37a86 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,42 @@ +2004-03-19 Mark Mitchell + + * call.c (build_op_delete_call): Do not forget the placement + arguments when iterating through mutiple delete operators. + + * cp-tree.h (svaed_scope): Remove last_parms. + (NEW_DELETE_OPNAME_P): New macro. + (last_function_parms): Remove. + (do_friend): Adjust prototype. + * decl.c (grokparms): Return the PARM_DECLs directly, rather than + using last_function_parms. + (grokfndecl): Take the PARM_DECLs as an argument, rather than + using last_function_parms. + (grokdeclarator): Adjust accordingly. Do not form METHOD_TYPEs + for class-specific operator new and operator delete. + (grok_op_properties): Do not look for allocation functions with + METHOD_TYPEs. + (start_function): Use DECL_ARGUMENTS instead of + last_function_parms. + * decl.h (last_function_parms): Do not declare. + * decl2.c (grokclassfn): Do not use last_function_parms. + * friend.c (do_friend): Remove parmdecls parameter. + * name-lookup.c (push_to_top_level): Do not save last_function_parms. + (pop_from_top_level): Do not restore it. + * pt.c (check_explicit_specialization): Do not adjust + last_function_parms. + + * name-lookup.c (do_local_using_decl): Create a local binding for + types brought in via using declarations. + + * name-lookup.c (lookup_arg_dependent): Handle block-scope + function declarations correctly. + + * semantics.c (finish_id_expression): Correct handling of + conversion operators to dependent types. + + * typeck.c (lookup_destructor): Allow the use of destructors from + base classes. + 2004-03-19 Richard Kenner * cxx-pretty-print.c (pp_cxx_unqualified_id): Use diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 7270ed6742d..06070fed130 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3979,15 +3979,15 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, /* On the first pass, check the rest of the arguments. */ if (pass == 0) { - while (argtypes && t) + tree a = argtypes; + while (a && t) { - if (!same_type_p (TREE_VALUE (argtypes), - TREE_VALUE (t))) + if (!same_type_p (TREE_VALUE (a), TREE_VALUE (t))) break; - argtypes = TREE_CHAIN (argtypes); + a = TREE_CHAIN (a); t = TREE_CHAIN (t); } - if (!argtypes && !t) + if (!a && !t) break; } /* On the second pass, the second argument must be diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 59cd2d594b9..839445cd2b6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -679,7 +679,6 @@ struct saved_scope GTY(()) tree x_previous_class_type; tree x_previous_class_values; tree x_saved_tree; - tree last_parms; HOST_WIDE_INT x_processing_template_decl; int x_processing_specialization; @@ -837,6 +836,14 @@ struct language_function GTY(()) #define current_function_return_value \ (cp_function_chain->x_return_value) +/* True if NAME is the IDENTIFIER_NODE for an overloaded "operator + new" or "operator delete". */ +#define NEW_DELETE_OPNAME_P(NAME) \ + ((NAME) == ansi_opname (NEW_EXPR) \ + || (NAME) == ansi_opname (VEC_NEW_EXPR) \ + || (NAME) == ansi_opname (DELETE_EXPR) \ + || (NAME) == ansi_opname (VEC_DELETE_EXPR)) + #define ansi_opname(CODE) \ (operator_name_info[(int) (CODE)].identifier) #define ansi_assopname(CODE) \ @@ -3693,7 +3700,6 @@ extern tree check_elaborated_type_specifier (enum tag_types, tree, bool); extern void warn_extern_redeclared_static (tree, tree); extern bool have_extern_spec; -extern GTY(()) tree last_function_parms; /* in decl2.c */ extern bool check_java_method (tree); @@ -3774,7 +3780,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, tree, enum overload_flags, tree, int); +extern tree do_friend (tree, tree, tree, tree, enum overload_flags, tree, int); /* in init.c */ extern tree expand_member_init (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 29d658859e6..b8a578f9ee0 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -52,7 +52,7 @@ Boston, MA 02111-1307, USA. */ #include "debug.h" #include "timevar.h" -static tree grokparms (tree); +static tree grokparms (tree, tree *); static const char *redeclaration_error_message (tree, tree); static int decl_jump_unsafe (tree); @@ -61,7 +61,7 @@ static int ambi_op_p (enum tree_code); static int unary_op_p (enum tree_code); static void push_local_name (tree); static tree grok_reference_init (tree, tree, tree, tree *); -static tree grokfndecl (tree, tree, tree, tree, int, +static tree grokfndecl (tree, tree, tree, tree, tree, int, enum overload_flags, tree, tree, int, int, int, int, int, int, tree); static tree grokvardecl (tree, tree, RID_BIT_TYPE *, int, int, tree); @@ -207,9 +207,6 @@ tree static_aggregates; tree integer_two_node, integer_three_node; -/* Similar, for last_function_parm_tags. */ -tree last_function_parms; - /* A list of all LABEL_DECLs in the function that have names. Here so we can clear out their names' definitions at the end of the function, and so we can check the validity of jumps to these labels. */ @@ -5419,6 +5416,7 @@ bad_specifiers (tree object, TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE or METHOD_TYPE. DECLARATOR is the function's name. + PARMS is a chain of PARM_DECLs for the function. VIRTUALP is truthvalue of whether the function is virtual or not. FLAGS are to be passed through to `grokclassfn'. QUALS are qualifiers indicating whether the function is `const' @@ -5434,6 +5432,7 @@ static tree grokfndecl (tree ctype, tree type, tree declarator, + tree parms, tree orig_declarator, int virtualp, enum overload_flags flags, @@ -5456,6 +5455,7 @@ grokfndecl (tree ctype, type = build_exception_variant (type, raises); decl = build_lang_decl (FUNCTION_DECL, declarator, type); + DECL_ARGUMENTS (decl) = parms; /* Propagate volatile out from type to decl. */ if (TYPE_VOLATILE (type)) TREE_THIS_VOLATILE (decl) = 1; @@ -5680,12 +5680,9 @@ grokfndecl (tree ctype, 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); - last_function_parms = TREE_CHAIN (last_function_parms); - } + /* 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 `%D'", old_decl); @@ -6339,6 +6336,7 @@ grokdeclarator (tree declarator, tree in_namespace = NULL_TREE; tree returned_attrs = NULL_TREE; tree scope = NULL_TREE; + tree parms = NULL_TREE; RIDBIT_RESET_ALL (specbits); if (decl_context == FUNCDEF) @@ -7411,7 +7409,7 @@ grokdeclarator (tree declarator, declarator = TREE_OPERAND (declarator, 0); - arg_types = grokparms (inner_parms); + arg_types = grokparms (inner_parms, &parms); if (declarator && flags == DTOR_FLAG) { @@ -7425,7 +7423,7 @@ grokdeclarator (tree declarator, { error ("destructors may not have parameters"); arg_types = void_list_node; - last_function_parms = NULL_TREE; + parms = NULL_TREE; } } @@ -7592,7 +7590,11 @@ grokdeclarator (tree declarator, } else if (TREE_CODE (type) == FUNCTION_TYPE) { - if (current_class_type == NULL_TREE || friendp) + if (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), @@ -7851,8 +7853,7 @@ grokdeclarator (tree declarator, type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE); /* Detect where we're using a typedef of function type to declare a - function. last_function_parms will not be set, so we must create - it now. */ + function. PARMS will not be set, so we must create it now. */ if (type == typedef_type && TREE_CODE (type) == FUNCTION_TYPE) { @@ -7867,7 +7868,7 @@ grokdeclarator (tree declarator, decls = decl; } - last_function_parms = nreverse (decls); + parms = nreverse (decls); } /* If this is a type name (such as, in a cast or sizeof), @@ -8061,10 +8062,7 @@ grokdeclarator (tree declarator, return void_type_node; } - if (declarator == ansi_opname (NEW_EXPR) - || declarator == ansi_opname (VEC_NEW_EXPR) - || declarator == ansi_opname (DELETE_EXPR) - || declarator == ansi_opname (VEC_DELETE_EXPR)) + if (NEW_DELETE_OPNAME_P (declarator)) { if (virtualp) { @@ -8087,6 +8085,7 @@ grokdeclarator (tree declarator, decl = grokfndecl (ctype, type, TREE_CODE (declarator) != TEMPLATE_ID_EXPR ? declarator : dname, + parms, declarator, virtualp, flags, quals, raises, friendp ? -1 : 0, friendp, publicp, inlinep, @@ -8133,6 +8132,7 @@ grokdeclarator (tree declarator, decl = grokfndecl (ctype, type, TREE_CODE (declarator) != TEMPLATE_ID_EXPR ? declarator : dname, + parms, declarator, virtualp, flags, quals, raises, friendp ? -1 : 0, friendp, 1, 0, funcdef_flag, @@ -8190,8 +8190,7 @@ grokdeclarator (tree declarator, } decl = do_friend (ctype, declarator, decl, - last_function_parms, *attrlist, - flags, quals, funcdef_flag); + *attrlist, flags, quals, funcdef_flag); return decl; } else @@ -8304,7 +8303,8 @@ grokdeclarator (tree declarator, virtualp = 0; } } - else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2) + else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2 + && !NEW_DELETE_OPNAME_P (original_name)) type = build_method_type_directly (ctype, TREE_TYPE (type), TYPE_ARG_TYPES (type)); @@ -8314,7 +8314,7 @@ grokdeclarator (tree declarator, || RIDBIT_SETP (RID_EXTERN, specbits) || !RIDBIT_SETP (RID_STATIC, specbits)); - decl = grokfndecl (ctype, type, original_name, declarator, + decl = grokfndecl (ctype, type, original_name, parms, declarator, virtualp, flags, quals, raises, 1, friendp, publicp, inlinep, funcdef_flag, @@ -8552,10 +8552,10 @@ check_default_argument (tree decl, tree arg) flag. If unset, we append void_list_node. A parmlist declared as `(void)' is accepted as the empty parmlist. - Also set last_function_parms to the chain of PARM_DECLs. */ + *PARMS is set to the chain of PARM_DECLs created. */ static tree -grokparms (tree first_parm) +grokparms (tree first_parm, tree *parms) { tree result = NULL_TREE; tree decls = NULL_TREE; @@ -8661,7 +8661,7 @@ grokparms (tree first_parm) result = nreverse (result); if (!ellipsis) result = chainon (result, void_list_node); - last_function_parms = decls; + *parms = decls; return result; } @@ -8914,21 +8914,9 @@ grok_op_properties (tree decl, int friendp, bool complain) } if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR) - { - /* When the compiler encounters the definition of A::operator new, it - doesn't look at the class declaration to find out if it's static. */ - if (methodp) - revert_static_member_fn (decl); - - TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl)); - } + TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl)); else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR) - { - if (methodp) - revert_static_member_fn (decl); - - TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl)); - } + TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl)); else { /* An operator function must either be a non-static member function @@ -10039,8 +10027,6 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags) else doing_friend = 1; } - - last_function_parms = DECL_ARGUMENTS (decl1); } else { @@ -10091,7 +10077,6 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags) && TREE_CODE (TREE_TYPE (decl1)) == METHOD_TYPE) { revert_static_member_fn (decl1); - last_function_parms = TREE_CHAIN (last_function_parms); ctype = NULL_TREE; } @@ -10138,7 +10123,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags) /* Save the parm names or decls from this function's declarator where store_parm_decls will find them. */ - current_function_parms = last_function_parms; + current_function_parms = DECL_ARGUMENTS (decl1); /* Make sure the parameter and return types are reasonable. When you declare a function, these types can be incomplete, but they diff --git a/gcc/cp/decl.h b/gcc/cp/decl.h index 2a7a7659e1b..46a1ec80688 100644 --- a/gcc/cp/decl.h +++ b/gcc/cp/decl.h @@ -33,10 +33,6 @@ enum decl_context /* We need this in here to get the decl_context definition. */ extern tree grokdeclarator (tree, tree, enum decl_context, int, tree*); -/* Parsing a function declarator leaves a list of parameter names - or a chain or parameter decls here. */ -extern GTY(()) tree last_function_parms; - #ifdef DEBUG_CP_BINDING_LEVELS /* Purely for debugging purposes. */ extern int debug_bindings_indentation; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index baf1adf9ed5..0a4e8e9d0d2 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -336,11 +336,10 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags, tree quals) qual_type = cp_build_qualified_type (type, this_quals); parm = build_artificial_parm (this_identifier, qual_type); c_apply_type_quals_to_decl (this_quals, parm); - TREE_CHAIN (parm) = last_function_parms; - last_function_parms = parm; + TREE_CHAIN (parm) = DECL_ARGUMENTS (function); + DECL_ARGUMENTS (function) = parm; } - DECL_ARGUMENTS (function) = last_function_parms; DECL_CONTEXT (function) = ctype; if (flags == DTOR_FLAG) diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index 46616b13608..297614c8381 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -314,17 +314,13 @@ make_friend_class (tree type, tree friend_type, bool complain) DECL is the FUNCTION_DECL that the friend is. - In case we are parsing a friend which is part of an inline - definition, we will need to store PARM_DECL chain that comes - with it into the DECL_ARGUMENTS slot of the FUNCTION_DECL. - FLAGS is just used for `grokclassfn'. QUALS say what special qualifies should apply to the object pointed to by `this'. */ tree -do_friend (tree ctype, tree declarator, tree decl, tree parmdecls, +do_friend (tree ctype, tree declarator, tree decl, tree attrlist, enum overload_flags flags, tree quals, int funcdef_flag) { @@ -424,7 +420,6 @@ do_friend (tree ctype, tree declarator, tree decl, tree parmdecls, Note that because classes all wind up being top-level in their scope, their friend wind up in top-level scope as well. */ - DECL_ARGUMENTS (decl) = parmdecls; if (funcdef_flag) SET_DECL_FRIEND_CONTEXT (decl, current_class_type); diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index e0a919d5b55..a23574248f7 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -2272,7 +2272,10 @@ do_local_using_decl (tree decl, tree scope, tree name) push_local_binding (name, newval, PUSH_USING); } if (newtype) - set_identifier_type_value (name, newtype); + { + push_local_binding (name, newtype, PUSH_USING); + set_identifier_type_value (name, newtype); + } /* Emit debug info. */ if (!processing_template_decl) @@ -4474,11 +4477,15 @@ lookup_arg_dependent (tree name, tree fns, tree args) we found were brought into the current namespace via a using declaration, we have not really checked the namespace from which they came. Therefore, we check all namespaces here -- unless the - function we have is from the current namespace. */ + function we have is from the current namespace. Even then, we + must check all namespaces if the function is a local + declaration; any other declarations present at namespace scope + should be visible during argument-dependent lookup. */ if (fns) fn = OVL_CURRENT (fns); if (fn && TREE_CODE (fn) == FUNCTION_DECL - && CP_DECL_CONTEXT (fn) != current_decl_namespace ()) + && (CP_DECL_CONTEXT (fn) != current_decl_namespace () + || DECL_LOCAL_FUNCTION_P (fn))) k.namespaces = NULL_TREE; else /* Setting NAMESPACES is purely an optimization; it prevents @@ -4835,7 +4842,6 @@ push_to_top_level (void) s->bindings = b; s->need_pop_function_context = need_pop; s->function_decl = current_function_decl; - s->last_parms = last_function_parms; scope_chain = s; current_function_decl = NULL_TREE; @@ -4873,7 +4879,6 @@ pop_from_top_level (void) if (s->need_pop_function_context) pop_function_context_from (NULL_TREE); current_function_decl = s->function_decl; - last_function_parms = s->last_parms; timevar_pop (TV_NAME_LOOKUP); } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3719410ad0d..be2f2c7c405 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -1910,15 +1910,10 @@ check_explicit_specialization (tree declarator, /* If we thought that the DECL was a member function, but it turns out to be specializing a static member function, - make DECL a static member function as well. We also have - to adjust last_function_parms to avoid confusing - start_function later. */ + make DECL a static member function as well. */ if (DECL_STATIC_FUNCTION_P (tmpl) && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) - { - revert_static_member_fn (decl); - last_function_parms = TREE_CHAIN (last_function_parms); - } + revert_static_member_fn (decl); /* If this is a specialization of a member template of a template class. In we want to return the TEMPLATE_DECL, diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 50cb153ec10..78896cce386 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2364,11 +2364,16 @@ finish_id_expression (tree id_expression, if (decl == error_mark_node) { /* Name lookup failed. */ - if (scope && (!TYPE_P (scope) || !dependent_type_p (scope))) + if (scope + && (!TYPE_P (scope) + || (!dependent_type_p (scope) + && !(TREE_CODE (id_expression) == IDENTIFIER_NODE + && IDENTIFIER_TYPENAME_P (id_expression) + && dependent_type_p (TREE_TYPE (id_expression)))))) { - /* Qualified name lookup failed, and the qualifying name - was not a dependent type. That is always an - error. */ + /* If the qualifying type is non-dependent (and the name + does not name a conversion operator to a dependent + type), issue an error. */ qualified_name_lookup_error (scope, id_expression); return error_mark_node; } @@ -2378,6 +2383,8 @@ finish_id_expression (tree id_expression, *idk = CP_ID_KIND_UNQUALIFIED; return id_expression; } + else + decl = id_expression; } /* If DECL is a variable that would be out of scope under ANSI/ISO rules, but in scope in the ARM, name lookup diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 32d8177b601..350a1d88719 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1788,6 +1788,7 @@ lookup_destructor (tree object, tree scope, tree dtor_name) { tree object_type = TREE_TYPE (object); tree dtor_type = TREE_OPERAND (dtor_name, 0); + tree expr; if (scope && !check_dtor_name (scope, dtor_name)) { @@ -1795,17 +1796,20 @@ lookup_destructor (tree object, tree scope, tree dtor_name) scope, dtor_type); return error_mark_node; } - if (!same_type_p (dtor_type, TYPE_MAIN_VARIANT (object_type))) + if (!DERIVED_FROM_P (dtor_type, TYPE_MAIN_VARIANT (object_type))) { error ("the type being destroyed is `%T', but the destructor refers to `%T'", TYPE_MAIN_VARIANT (object_type), dtor_type); return error_mark_node; } - if (!TYPE_HAS_DESTRUCTOR (object_type)) + if (!TYPE_HAS_DESTRUCTOR (dtor_type)) return build (PSEUDO_DTOR_EXPR, void_type_node, object, scope, dtor_type); - return lookup_member (object_type, complete_dtor_identifier, + expr = lookup_member (dtor_type, complete_dtor_identifier, /*protect=*/1, /*want_type=*/false); + expr = (adjust_result_of_qualified_name_lookup + (expr, dtor_type, object_type)); + return expr; } /* This function is called by the parser to process a class member diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 362359e7a8f..213613e51f0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,20 @@ +2004-03-19 Mark Mitchell + + * g++.dg/init/placement3.C: New test. + + * g++.dg/template/spec13.C: New test. + + * g++.dg/lookup/using11.C: New test. + + * g++.dg/lookup/koenig3.C: New test. + + * g++.dg/template/operator2.C: New test. + + * g++.dg/expr/dtor3.C: New test. + * g++.old-deja/g++.brendan/crash15.C: Remove incorrect dg-error + marker. + * g++.old-deja/g++.law/visibility28.C: Likewise. + 2004-03-19 Paolo Bonzini * gcc.dg/altivec-6.c: Use vector_size attribute, not mode. diff --git a/gcc/testsuite/g++.dg/expr/dtor3.C b/gcc/testsuite/g++.dg/expr/dtor3.C new file mode 100644 index 00000000000..036e9f2a010 --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/dtor3.C @@ -0,0 +1,10 @@ +struct B { + ~B(); +}; +struct D : public B { + ~D(); +}; + +void f(D d) { + d.B::~B(); +} diff --git a/gcc/testsuite/g++.dg/init/placement3.C b/gcc/testsuite/g++.dg/init/placement3.C new file mode 100644 index 00000000000..919e2a81617 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/placement3.C @@ -0,0 +1,30 @@ +typedef __SIZE_TYPE__ size_t; +extern "C" void *malloc (size_t); + +int i; + +struct S { + S(int) { + throw 3; + } + + void *operator new(size_t s, int) { + ++i; + return malloc (s); + } + + void operator delete(void *, int) { + --i; + } + + void operator delete(void *, int, int) ; +}; + +int main () { + try { + new (7) S (12); + } catch (int) { + if (i) + return 1; + } +} diff --git a/gcc/testsuite/g++.dg/lookup/koenig3.C b/gcc/testsuite/g++.dg/lookup/koenig3.C new file mode 100644 index 00000000000..c5dedbe708e --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/koenig3.C @@ -0,0 +1,13 @@ +extern "C" void abort (); + +struct S { +}; +void f(S, int) { abort(); } +void f(S, double) {} + +S s; + +int main() { + extern void f(S, int); + f(s, 3.0); +} diff --git a/gcc/testsuite/g++.dg/lookup/using11.C b/gcc/testsuite/g++.dg/lookup/using11.C new file mode 100644 index 00000000000..9eb7e9fe7a1 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/using11.C @@ -0,0 +1,9 @@ +namespace N1 { + enum e { a }; + void e(char); +} + +void f() { + using N1::e; + enum e x; +} diff --git a/gcc/testsuite/g++.dg/template/operator2.C b/gcc/testsuite/g++.dg/template/operator2.C new file mode 100644 index 00000000000..89f428d5fc5 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/operator2.C @@ -0,0 +1,8 @@ +template struct A {}; + +struct B { + operator A(); +}; + +template +void f() { B::operator A; } diff --git a/gcc/testsuite/g++.dg/template/spec13.C b/gcc/testsuite/g++.dg/template/spec13.C new file mode 100644 index 00000000000..f2a3a373ed7 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/spec13.C @@ -0,0 +1,16 @@ +// { dg-options "-w" } + +template +struct S { + int i; + template void f(U) {} +}; + +template<> +template +void S::f(U) { i; } + +void f() { + S s; + s.f(3); +} diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash15.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash15.C index 28e3253c192..3c59fa64b43 100644 --- a/gcc/testsuite/g++.old-deja/g++.brendan/crash15.C +++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash15.C @@ -16,7 +16,7 @@ int main() { std::cout << "starting\n"; B b; - b.~A();// { dg-error "" } destructor + b.~A(); std::cout << "done\n"; } diff --git a/gcc/testsuite/g++.old-deja/g++.law/visibility28.C b/gcc/testsuite/g++.old-deja/g++.law/visibility28.C index b1458e5955a..a7141ae5ea7 100644 --- a/gcc/testsuite/g++.old-deja/g++.law/visibility28.C +++ b/gcc/testsuite/g++.old-deja/g++.law/visibility28.C @@ -11,7 +11,7 @@ public: class D : public B { public: virtual ~D() { printf( "D::~D\n"); } - void operator = ( int i) { this->~B(); }// { dg-error "" } D has no ~B part to it + void operator = ( int i) { this->~B(); } }; int