OSDN Git Service

* call.c (build_op_delete_call): Do not forget the placement
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 20 Mar 2004 00:18:24 +0000 (00:18 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 20 Mar 2004 00:18:24 +0000 (00:18 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@79722 138bc75d-0d04-0410-961f-82ee72b054a4

20 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl.h
gcc/cp/decl2.c
gcc/cp/friend.c
gcc/cp/name-lookup.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/expr/dtor3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/placement3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/koenig3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/using11.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/operator2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/spec13.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.brendan/crash15.C
gcc/testsuite/g++.old-deja/g++.law/visibility28.C

index 7c8c1d2..654e6a3 100644 (file)
@@ -1,3 +1,42 @@
+2004-03-19  Mark Mitchell  <mark@codesourcery.com>
+
+       * 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  <kenner@vlsi1.ultra.nyu.edu>
 
        * cxx-pretty-print.c (pp_cxx_unqualified_id): Use
index 7270ed6..06070fe 100644 (file)
@@ -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
index 59cd2d5..839445c 100644 (file)
@@ -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);
index 29d6588..b8a578f 100644 (file)
@@ -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
index 2a7a765..46a1ec8 100644 (file)
@@ -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;
index baf1adf..0a4e8e9 100644 (file)
@@ -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)
index 46616b1..297614c 100644 (file)
@@ -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);
 
index e0a919d..a235742 100644 (file)
@@ -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);
 }
 
index 3719410..be2f2c7 100644 (file)
@@ -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,
index 50cb153..78896cc 100644 (file)
@@ -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
index 32d8177..350a1d8 100644 (file)
@@ -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
index 362359e..213613e 100644 (file)
@@ -1,3 +1,20 @@
+2004-03-19  Mark Mitchell  <mark@codesourcery.com>
+
+       * 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  <bonzini@gnu.org>
 
        * 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 (file)
index 0000000..036e9f2
--- /dev/null
@@ -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 (file)
index 0000000..919e2a8
--- /dev/null
@@ -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 (file)
index 0000000..c5dedbe
--- /dev/null
@@ -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 (file)
index 0000000..9eb7e9f
--- /dev/null
@@ -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 (file)
index 0000000..89f428d
--- /dev/null
@@ -0,0 +1,8 @@
+template <typename T> struct A {};
+
+struct B {
+  operator A<B>();
+};
+
+template <typename T>
+void f() { B::operator A<T>; }
diff --git a/gcc/testsuite/g++.dg/template/spec13.C b/gcc/testsuite/g++.dg/template/spec13.C
new file mode 100644 (file)
index 0000000..f2a3a37
--- /dev/null
@@ -0,0 +1,16 @@
+// { dg-options "-w" }
+
+template <typename T>
+struct S {
+  int i;
+  template <typename U> void f(U) {}
+};
+
+template<> 
+template <typename U>
+void S<int>::f(U) { i; }
+
+void f() {
+  S<int> s;
+  s.f<int>(3);
+}
index 28e3253..3c59fa6 100644 (file)
@@ -16,7 +16,7 @@ int
 main() {
   std::cout << "starting\n";
   B b;
-  b.~A();// { dg-error "" }  destructor
+  b.~A();
   std::cout << "done\n";
 }
 
index b1458e5..a7141ae 100644 (file)
@@ -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