class.c (pushclass): Tweak handling of class-level bindings.
authorMark Mitchell <mark@markmitchell.com>
Mon, 14 Dec 1998 15:35:40 +0000 (15:35 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 14 Dec 1998 15:35:40 +0000 (15:35 +0000)
* class.c (pushclass): Tweak handling of class-level bindings.
(resolve_address_of_overloaded_function): Update pointer-to-member
handling.
(instantiate_type): Likewise.
* cvt.c (cp_convert_to_pointer): Likewise.
* decl.c (pop_binding): Take the DECL to pop, not just the name.
Deal with `struct stat' hack.
(binding_level): Add to documentation.
(push_binding): Clear BINDING_TYPE.
(add_binding): New function.
(push_local_binding): Use it.
(push_class_binding): Likewise.
(poplevel): Adjust calls to pop_binding.
(poplevel_class): Likewise.
(pushdecl): Adjust handling of TYPE_DECLs; add bindings for hidden
declarations to current binding level.
(push_class_level_binding): Likewise.
(push_overloaded_decl): Adjust handling of OVERLOADs in local
bindings.
(lookup_namespace_name): Don't crash when confronted with a
TEMPLATE_DECL.
(lookup_name_real): Do `struct stat' hack in local binding
contexts.
(build_ptrmemfunc_type): Adjust documentation.
(grokdeclarator): Don't avoid building real array types when
processing templates unless really necessary.
(finish_method): Adjust calls to pop_binding.
* decl2.c (reparse_absdcl_as_expr): Recursively call ourselves,
not reparse_decl_as_expr.
(build_expr_from_tree): Deal with a template-id as the function to
call in a METHOD_CALL_EXPR.
* pt.c (convert_nontype_argument): Tweak pointer-to-member handling.
(maybe_adjust_types_For_deduction): Don't do peculiar things with
METHOD_TYPEs here.
(resolve_overloaded_unification): Handle COMPONENT_REFs.  Build
pointer-to-member types where necessary.
* tree.c (build_cplus_array_type_1): Don't avoid building real
array types when processing templates unless really necessary.
(build_exception_variant): Compare the exception lists correctly.

From-SVN: r24314

15 files changed:
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/testsuite/g++.old-deja/g++.eh/tmpl3.C
gcc/testsuite/g++.old-deja/g++.ns/crash3.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/expr1.C
gcc/testsuite/g++.old-deja/g++.other/lookup8.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/array2.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/memtemp81.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/overload11.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/ptrmem4.C [new file with mode: 0644]

index 84cc28fa1b7d0ddb21b22fc1db13ddf8700d048f..78658fd0169909795d05419c86b180dc0c2066f5 100644 (file)
@@ -1,3 +1,45 @@
+1998-12-14  Mark Mitchell  <mark@markmitchell.com>
+
+       * class.c (pushclass): Tweak handling of class-level bindings.
+       (resolve_address_of_overloaded_function): Update pointer-to-member
+       handling. 
+       (instantiate_type): Likewise.
+       * cvt.c (cp_convert_to_pointer): Likewise.
+       * decl.c (pop_binding): Take the DECL to pop, not just the name.
+       Deal with `struct stat' hack.
+       (binding_level): Add to documentation.
+       (push_binding): Clear BINDING_TYPE.
+       (add_binding): New function.
+       (push_local_binding): Use it.
+       (push_class_binding): Likewise.
+       (poplevel): Adjust calls to pop_binding.
+       (poplevel_class): Likewise.
+       (pushdecl): Adjust handling of TYPE_DECLs; add bindings for hidden
+       declarations to current binding level.
+       (push_class_level_binding): Likewise.
+       (push_overloaded_decl): Adjust handling of OVERLOADs in local
+       bindings. 
+       (lookup_namespace_name): Don't crash when confronted with a
+       TEMPLATE_DECL. 
+       (lookup_name_real): Do `struct stat' hack in local binding
+       contexts. 
+       (build_ptrmemfunc_type): Adjust documentation.
+       (grokdeclarator): Don't avoid building real array types when
+       processing templates unless really necessary.
+       (finish_method): Adjust calls to pop_binding.
+       * decl2.c (reparse_absdcl_as_expr): Recursively call ourselves,
+       not reparse_decl_as_expr.
+       (build_expr_from_tree): Deal with a template-id as the function to
+       call in a METHOD_CALL_EXPR.
+       * pt.c (convert_nontype_argument): Tweak pointer-to-member handling.
+       (maybe_adjust_types_For_deduction): Don't do peculiar things with
+       METHOD_TYPEs here.
+       (resolve_overloaded_unification): Handle COMPONENT_REFs.  Build
+       pointer-to-member types where necessary.
+       * tree.c (build_cplus_array_type_1): Don't avoid building real
+       array types when processing templates unless really necessary.
+       (build_exception_variant): Compare the exception lists correctly. 
+       
 1998-12-13  Mark Mitchell  <mark@markmitchell.com>
 
        * cp-tree.def (CPLUS_BINDING): Update documentation.
index 5031b55691758579ef6f341b69c6ded098f14286..e3f4544481b0c26505fcda2b172f32c3bc427c5e 100644 (file)
@@ -4789,7 +4789,7 @@ pushclass (type, modify)
          for (item = previous_class_values; item; item = TREE_CHAIN (item))
            {
              tree id = TREE_PURPOSE (item);
-             tree decl = IDENTIFIER_CLASS_VALUE (id);
+             tree decl = TREE_TYPE (item);
 
              push_class_binding (id, decl);
              if (TREE_CODE (decl) == TYPE_DECL)
@@ -4808,8 +4808,6 @@ pushclass (type, modify)
          if (! (IS_AGGR_TYPE_CODE (TREE_CODE (tag_type))
                 && CLASSTYPE_IS_TEMPLATE (tag_type)))
            pushtag (TREE_PURPOSE (tags), tag_type, 0);
-         else
-           pushdecl_class_level (CLASSTYPE_TI_TEMPLATE (tag_type));
        }
 
       current_function_decl = this_fndecl;
@@ -5028,11 +5026,12 @@ resolve_address_of_overloaded_function (target_type,
      interoperability with most_specialized_instantiation.  */
   tree matches = NULL_TREE;
 
-  /* If the TARGET_TYPE is a pointer-to-a-method, we convert it to
-     proper pointer-to-member type here.  */
-  if (TREE_CODE (target_type) == POINTER_TYPE
-      && TREE_CODE (TREE_TYPE (target_type)) == METHOD_TYPE)
-    target_type = build_ptrmemfunc_type (target_type);
+  /* By the time we get here, we should be seeing only real
+     pointer-to-member types, not the internal POINTER_TYPE to
+     METHOD_TYPE representation.  */
+  my_friendly_assert (!(TREE_CODE (target_type) == POINTER_TYPE
+                       && (TREE_CODE (TREE_TYPE (target_type)) 
+                           == METHOD_TYPE)), 0);
 
   /* Check that the TARGET_TYPE is reasonable.  */
   if (TYPE_PTRFN_P (target_type))
@@ -5475,15 +5474,20 @@ instantiate_type (lhstype, rhs, complain)
        if (fn == error_mark_node)
          return error_mark_node;
        mark_addressable (fn);
-       TREE_TYPE (rhs) = lhstype;
        TREE_OPERAND (rhs, 0) = fn;
        TREE_CONSTANT (rhs) = staticp (fn);
-       if (TREE_CODE (lhstype) == POINTER_TYPE
-           && TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE)
+       if (TYPE_PTRMEMFUNC_P (lhstype))
          {
-           build_ptrmemfunc_type (lhstype);
-           rhs = build_ptrmemfunc (lhstype, rhs, 0);
+           /* We must use the POINTER_TYPE to METHOD_TYPE on RHS here
+              so that build_ptrmemfunc knows that RHS we have is not
+              already a pointer-to-member constant.  Instead, it is
+              just a ADDR_EXPR over a FUNCTION_DECL.  */
+           TREE_TYPE (rhs) = TYPE_PTRMEMFUNC_FN_TYPE (lhstype);
+           rhs = build_ptrmemfunc (TREE_TYPE (rhs), rhs, 0);
          }
+       else
+         /* Here, things our simple; we have exactly what we need.  */
+         TREE_TYPE (rhs) = lhstype;
       }
       return rhs;
 
index a5a91c162382f278318a11fe29e6fe9dcc5b17dd..c8f9fcc57e9b7bc30b6e76f0d4e7ce8b7afd1966 100644 (file)
@@ -95,9 +95,6 @@ cp_convert_to_pointer (type, expr)
        }
     }
 
-  if (TYPE_PTRMEMFUNC_P (type))
-    type = TYPE_PTRMEMFUNC_FN_TYPE (type);
-
   /* Handle anachronistic conversions from (::*)() to cv void* or (*)().  */
   if (TREE_CODE (type) == POINTER_TYPE
       && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
@@ -128,16 +125,14 @@ cp_convert_to_pointer (type, expr)
       intype = TREE_TYPE (expr);
     }
 
-  if (TYPE_PTRMEMFUNC_P (intype))
-    intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
-
   form = TREE_CODE (intype);
 
-  if (form == POINTER_TYPE || form == REFERENCE_TYPE)
+  if (POINTER_TYPE_P (intype))
     {
       intype = TYPE_MAIN_VARIANT (intype);
 
       if (TYPE_MAIN_VARIANT (type) != intype
+         && TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
          && IS_AGGR_TYPE (TREE_TYPE (type))
          && IS_AGGR_TYPE (TREE_TYPE (intype))
@@ -181,12 +176,9 @@ cp_convert_to_pointer (type, expr)
                }
            }
        }
-      if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE
-         && TREE_CODE (type) == POINTER_TYPE
-         && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
-       return build_ptrmemfunc (type, expr, 1);
 
-      if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
+      if (TREE_CODE (type) == POINTER_TYPE
+         && TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
          && TREE_CODE (TREE_TYPE (intype)) == OFFSET_TYPE)
        {
          tree b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type));
@@ -205,10 +197,7 @@ cp_convert_to_pointer (type, expr)
          if (binfo && ! TREE_VIA_VIRTUAL (binfo))
            expr = size_binop (code, expr, BINFO_OFFSET (binfo));
        }
-
-      if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE
-         || (TREE_CODE (type) == POINTER_TYPE
-             && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
+      else if (TYPE_PTRMEMFUNC_P (type))
        {
          cp_error ("cannot convert `%E' from type `%T' to type `%T'",
                    expr, intype, type);
@@ -219,6 +208,14 @@ cp_convert_to_pointer (type, expr)
       TREE_CONSTANT (rval) = TREE_CONSTANT (expr);
       return rval;
     }
+  else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
+    return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 1);
+  else if (TYPE_PTRMEMFUNC_P (intype))
+    {
+      cp_error ("cannot convert `%E' from type `%T' to type `%T'",
+               expr, intype, type);
+      return error_mark_node;
+    }
 
   my_friendly_assert (form != OFFSET_TYPE, 186);
 
@@ -228,7 +225,7 @@ cp_convert_to_pointer (type, expr)
 
   if (integer_zerop (expr))
     {
-      if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
+      if (TYPE_PTRMEMFUNC_P (type))
        return build_ptrmemfunc (type, expr, 0);
       expr = build_int_2 (0, 0);
       TREE_TYPE (expr) = type;
index 7c9a518e1617eb5fd04236fb865fbfcad1e510dd..8940acb3ea003cdf6bc977aa2360d7960499270c 100644 (file)
@@ -180,7 +180,8 @@ static void check_for_uninitialized_const_var PROTO((tree));
 static unsigned long typename_hash PROTO((hash_table_key));
 static boolean typename_compare PROTO((hash_table_key, hash_table_key));
 static void push_binding PROTO((tree, tree, struct binding_level*));
-static void pop_binding PROTO((tree));
+static void add_binding PROTO((tree, tree));
+static void pop_binding PROTO((tree, tree));
 
 #if defined (DEBUG_CP_BINDING_LEVELS)
 static void indent PROTO((void));
@@ -602,7 +603,10 @@ push_decl_level (stack, obstack)
    to catch class-local declarations.  It is otherwise nonexistent.
 
    Also there may be binding levels that catch cleanups that must be
-   run when exceptions occur.  */
+   run when exceptions occur.  Thus, to see whether a name is bound in
+   the current scope, it is not enough to look in the
+   CURRENT_BINDING_LEVEL.  You should use lookup_name_current_level
+   instead.  */
 
 /* Note that the information in the `names' component of the global contour
    is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers.  */
@@ -637,7 +641,8 @@ struct binding_level
        is the name of an entity bound in the class; the TREE_VALUE is
        the IDENTIFIER_CLASS_VALUE before we entered the class.  Thus,
        when leaving class scope, we can restore the
-       IDENTIFIER_CLASS_VALUE by walking this list.  */
+       IDENTIFIER_CLASS_VALUE by walking this list.  The TREE_TYPE is
+       the DECL bound by this name in the class.  */
     tree class_shadowed;
 
     /* Similar to class_shadowed, but for IDENTIFIER_TYPE_VALUE, and
@@ -1072,6 +1077,7 @@ push_binding (id, decl, level)
 
   /* Now, fill in the binding information.  */
   BINDING_VALUE (binding) = decl;
+  BINDING_TYPE (binding) = NULL_TREE;
   BINDING_LEVEL (binding) = level;
   LOCAL_BINDING_P (binding) = (level != class_binding_level);
 
@@ -1080,6 +1086,38 @@ push_binding (id, decl, level)
   IDENTIFIER_BINDING (id) = binding;
 }
 
+/* ID is already bound in the current scope.  But, DECL is an
+   additional binding for ID in the same scope.  This is the `struct
+   stat' hack whereby a non-typedef class-name or enum-name can be
+   bound at the same level as some other kind of entity.  It's the
+   responsibility of the caller to check that inserting this name is
+   legal here.  */
+static void
+add_binding (id, decl)
+     tree id;
+     tree decl;
+{
+  tree binding = IDENTIFIER_BINDING (id);
+
+  if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
+    /* The new name is the type name.  */
+    BINDING_TYPE (binding) = decl;
+  else 
+    {
+      /* The old name must be the type name.  It was placed in
+        IDENTIFIER_VALUE because it was thought, at the point it
+        was declared, to be the only entity with such a name.  */
+      my_friendly_assert (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+                         && DECL_ARTIFICIAL (BINDING_VALUE (binding)),
+                         0);
+
+      /* Move the type name into the type slot; it is now hidden by
+        the new binding.  */
+      BINDING_TYPE (binding) = BINDING_VALUE (binding);
+      BINDING_VALUE (binding) = decl;
+    }
+}
+
 /* Bind DECL to ID in the current_binding_level.  */
 
 void
@@ -1087,15 +1125,19 @@ push_local_binding (id, decl)
      tree id;
      tree decl;
 {
-  tree d = decl;;
+  tree d = decl;
 
   if (TREE_CODE (decl) == OVERLOAD)
     /* We must put the OVERLOAD into a TREE_LIST since the
        TREE_CHAIN of an OVERLOAD is already used.  */
     decl = build_tree_list (NULL_TREE, decl);
 
-  /* Create a binding, hanging off of ID.  */
-  push_binding (id, d, current_binding_level);
+  if (lookup_name_current_level (id))
+    /* Supplement the existing binding.  */
+    add_binding (id, decl);
+  else
+    /* Create a new binding.  */
+    push_binding (id, d, current_binding_level);
 
   /* And put DECL on the list of things declared by the current
      binding level.  */
@@ -1110,32 +1152,63 @@ push_class_binding (id, decl)
      tree id;
      tree decl;
 {
-  push_binding (id, decl, class_binding_level);
+  if (IDENTIFIER_BINDING (id)
+      && BINDING_LEVEL (IDENTIFIER_BINDING (id)) == class_binding_level)
+    /* Supplement the existing binding.  */
+    add_binding (id, decl);
+  else
+    /* Create a new binding.  */
+    push_binding (id, decl, class_binding_level);
+
+  /* Update the IDENTIFIER_CLASS_VALUE for this ID to be the
+     class-level declaration.  Note that we do not use DECL here
+     because of the possibility of the `struct stat' hack; if DECL is
+     a class-name or enum-name we might prefer a field-name, or some
+     such.  */
+  IDENTIFIER_CLASS_VALUE (id) = BINDING_VALUE (IDENTIFIER_BINDING (id));
 }
 
-/* Remove the innermost binding for ID; it has gone out of scope.  */
+/* Remove the binding for DECL which should be the innermost binding
+   for ID.  */
 
 static void 
-pop_binding (id) 
+pop_binding (id, decl
      tree id;
+     tree decl;
 {
   tree binding;
-
+    
   if (id == NULL_TREE)
     /* It's easiest to write the loops that call this function without
        checking whether or not the entities involved have names.  We
        get here for such an entity.  */
     return;
 
-  my_friendly_assert (IDENTIFIER_BINDING (id) != NULL_TREE, 0);
-
-  /* Unhook the innermost binding from the list of bindings.  */
+  /* Get the innermost binding for ID.  */
   binding = IDENTIFIER_BINDING (id);
-  IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
 
-  /* And place this list node on the free list.  */
-  TREE_CHAIN (binding) = free_binding_nodes;
-  free_binding_nodes = binding;
+  /* The name should be bound.  */
+  my_friendly_assert (binding != NULL_TREE, 0);
+
+  /* The DECL will be either the ordinary binding or the type
+     binding for this identifier.  Remove that binding.  */
+  if (BINDING_VALUE (binding) == decl)
+    BINDING_VALUE (binding) = NULL_TREE;
+  else if (BINDING_TYPE (binding) == decl)
+    BINDING_TYPE (binding) = NULL_TREE;
+  else
+    my_friendly_abort (0);
+
+  if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding))
+    {
+      /* We're completely done with the innermost binding for this
+        identifier.  Unhook it from the list of bindings.  */
+      IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
+
+      /* And place it on the free list.  */
+      TREE_CHAIN (binding) = free_binding_nodes;
+      free_binding_nodes = binding;
+    }
 }
 
 /* Exit a binding level.
@@ -1303,7 +1376,7 @@ poplevel (keep, reverse, functionbody)
                 
               and we are leaving the `for' scope.  There's no reason to
               keep the binding of the inner `i' in this case.  */
-           pop_binding (DECL_NAME (link));
+           pop_binding (DECL_NAME (link), link);
          else if ((outer_binding 
                    && (TREE_CODE (BINDING_VALUE (outer_binding)) 
                        == TYPE_DECL))
@@ -1319,7 +1392,7 @@ poplevel (keep, reverse, functionbody)
 
               We must pop the for-scope binding so we know what's a
               type and what isn't.  */
-           pop_binding (DECL_NAME (link));
+           pop_binding (DECL_NAME (link), link);
          else
            {
              /* Mark this VAR_DECL as dead so that we can tell we left it
@@ -1350,10 +1423,11 @@ poplevel (keep, reverse, functionbody)
        {
          /* Remove the binding.  */
          if (TREE_CODE_CLASS (TREE_CODE (link)) == 'd')
-           pop_binding (DECL_NAME (link));
+           pop_binding (DECL_NAME (link), link);
          else if (TREE_CODE (link) == TREE_LIST)
-           pop_binding (DECL_NAME (OVL_FUNCTION (TREE_VALUE (link))));
-         else
+           pop_binding (DECL_NAME (OVL_FUNCTION (TREE_VALUE (link))), 
+                        TREE_VALUE (link));
+         else 
            my_friendly_abort (0);
        }
     }
@@ -1362,7 +1436,7 @@ poplevel (keep, reverse, functionbody)
      that we kept around.  */
   for (link = current_binding_level->dead_vars_from_for;
        link; link = TREE_CHAIN (link))
-    pop_binding (DECL_NAME (TREE_VALUE (link)));
+    pop_binding (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link));
 
   /* Restore the IDENTIFIER_TYPE_VALUEs.  */
   for (link = current_binding_level->type_shadowed;
@@ -1607,7 +1681,7 @@ poplevel_class (force)
   for (shadowed = level->class_shadowed; 
        shadowed; 
        shadowed = TREE_CHAIN (shadowed))
-    pop_binding (TREE_PURPOSE (shadowed));
+    pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (shadowed));
 
   GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level,
                      (HOST_WIDE_INT) class_binding_level->level_chain,
@@ -3617,12 +3691,6 @@ pushdecl (x)
             set_identifier_type_value_with_scope (DECL_NAME (x), type, 
                                                  current_binding_level);
 
-         if (TREE_CODE (x) == TYPE_DECL
-             && DECL_ARTIFICIAL (x)
-             && t != NULL_TREE)
-           /* We don't want an artificial TYPE_DECL is we already
-              have another DECL with the same name.  */
-           need_new_binding = 0;
        }
 
       /* Multiple external decls of the same identifier ought to match.
@@ -3663,7 +3731,8 @@ pushdecl (x)
          if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
            TREE_PUBLIC (name) = 1;
 
-         if (need_new_binding)
+         if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
+               && t != NULL_TREE))
            {
              if (TREE_CODE (x) == FUNCTION_DECL)
                my_friendly_assert 
@@ -3999,23 +4068,20 @@ push_class_level_binding (name, x)
   if (!class_binding_level)
     return;
 
-  if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
-      && purpose_member (name, class_binding_level->class_shadowed))
-    return;
-
   /* If this declaration shadows a declaration from an enclosing
      class, then we will need to restore IDENTIFIER_CLASS_VALUE when
      we leave this class.  Record the shadowed declaration here.  */
   maybe_push_cache_obstack ();
   class_binding_level->class_shadowed
-      = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
-                  class_binding_level->class_shadowed);
+    = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
+                class_binding_level->class_shadowed);
+  TREE_TYPE (class_binding_level->class_shadowed)
+    = x;
   pop_obstacks ();
 
   /* Put the binding on the stack of bindings for the identifier, and
      update IDENTIFIER_CLASS_VALUE.  */
   push_class_binding (name, x);
-  IDENTIFIER_CLASS_VALUE (name) = x;
 
   obstack_ptr_grow (&decl_obstack, x);
 }
@@ -4155,8 +4221,8 @@ push_overloaded_decl (decl, forgettable)
       /* We only create an OVERLOAD if there was a previous binding at
         this level.  In that case, we need to remove the old binding
         and replace it with the new binding.  We must also run
-        through the NAMES on the current binding level to update the
-        chain.  */
+        through the NAMES on the binding level where the name was
+        bound to update the chain.  */
       if (TREE_CODE (new_binding) == OVERLOAD)
        {
          tree *d;
@@ -4168,11 +4234,21 @@ push_overloaded_decl (decl, forgettable)
                || (TREE_CODE (*d) == TREE_LIST
                    && TREE_VALUE (*d) == old))
              {
-               *d = TREE_CHAIN (*d);
-               break;
+               if (TREE_CODE (*d) == TREE_LIST)
+                 /* Just replace the old binding with the new.  */
+                 TREE_VALUE (*d) = new_binding;
+               else
+                 /* Build a TREE_LIST to wrap the OVERLOAD.  */
+                 *d = build_tree_list (NULL_TREE, new_binding);
+
+               /* And update the CPLUS_BINDING node.  */
+               BINDING_VALUE (IDENTIFIER_BINDING (name))
+                 = new_binding;
+               return decl;
              }
 
-         pop_binding (name);
+         /* We should always find a previous binding in this case.  */
+         my_friendly_abort (0);
        }
 
       /* Install the new binding.  */
@@ -4887,9 +4963,16 @@ lookup_namespace_name (namespace, name)
 
   my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
 
-  /* This happens for A::B<int> when B is a namespace. */
   if (TREE_CODE (name) == NAMESPACE_DECL)
+    /* This happens for A::B<int> when B is a namespace. */
     return name;
+  else if (TREE_CODE (name) == TEMPLATE_DECL)
+    {
+      /* This happens for A::B where B is a template, and there are no
+        template arguments.  */
+      cp_error ("invalid use of `%D'", name);
+      return error_mark_node;
+    }
 
   my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
   
@@ -5321,15 +5404,27 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
   else
     flags = lookup_flags (prefer_type, namespaces_only);
 
-  /* First, look in a non-global scope, carefully avoiding any
-     class-scope bindings if required.  */
+  /* First, look in non-namespace scopes.  */
   val = IDENTIFIER_BINDING (name); 
-  while (val && nonclass && !LOCAL_BINDING_P (val))
-    val = TREE_CHAIN (val);
-
-  /* Get the DECL actually bound.  */
-  if (val)
-    val = BINDING_VALUE (val);
+  for (val = IDENTIFIER_BINDING (name); val; val = TREE_CHAIN (val))
+    {
+      if (!LOCAL_BINDING_P (val) && nonclass)
+       /* We're not looking for class-scoped bindings, so keep going.  */
+       continue;
+      
+      /* If this is the kind of thing we're looking for, we're done.  */
+      if (qualify_lookup (BINDING_VALUE (val), flags))
+       {
+         val = BINDING_VALUE (val);
+         break;
+       }
+      else if ((flags & LOOKUP_PREFER_TYPES) 
+              && qualify_lookup (BINDING_TYPE (val), flags))
+       {
+         val = BINDING_TYPE (val);
+         break;
+       }
+    }
 
   /* If VAL is a type from a dependent base, we're not really supposed
      to be able to see it; the fact that we can is the "implicit
@@ -5342,10 +5437,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
       && uses_template_parms (current_class_type))
     val = lookup_field (current_class_type, name, 0, 1);
 
-  /* Make sure that this binding is the sort of thing we're looking
-     for.  */
-  val = qualify_lookup (val, flags);
-
   /* We don't put names from baseclasses onto the IDENTIFIER_BINDING
      list when we're defining a type.  It would probably be simpler to
      do this, but we don't.  So, we must lookup names from base
@@ -5361,8 +5452,8 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
     }
   
   /* If we found a type from a dependent base class (using the
-     implicit typename extension), turn it into the TYPE_DECL for a
-     TYPENAME_TYPE here.  */
+     implicit typename extension) make sure that there's not some
+     global name which should be chosen instead.  */
   if (val && TREE_CODE (val) == TYPE_DECL
       && IMPLICIT_TYPENAME_P (TREE_TYPE (val)))
     {
@@ -8575,7 +8666,8 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
   return decl;
 }
 
-/* Create a canonical pointer to member function type.  */
+/* Create and return a canonical pointer to member function type, for
+   TYPE, which is a POINTER_TYPE to a METHOD_TYPE.  */
 
 tree
 build_ptrmemfunc_type (type)
@@ -9790,7 +9882,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
                /* If this involves a template parameter, it'll be
                   constant, but we don't know what the value is yet.  */
-               if (processing_template_decl)
+               if (uses_template_parms (size))
                  {
                    /* Resolve a qualified reference to an enumerator or
                       static const data member of ours.  */
@@ -10141,9 +10233,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                type = build_reference_type (type);
            }
          else if (TREE_CODE (type) == METHOD_TYPE)
-           {
-             type = build_ptrmemfunc_type (build_pointer_type (type));
-           }
+           type = build_ptrmemfunc_type (build_pointer_type (type));
          else
            type = build_pointer_type (type);
 
@@ -13976,7 +14066,7 @@ finish_method (decl)
   for (link = current_binding_level->names; link; link = TREE_CHAIN (link))
     {
       if (DECL_NAME (link) != NULL_TREE)
-       pop_binding (DECL_NAME (link));
+       pop_binding (DECL_NAME (link), link);
       my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163);
       DECL_CONTEXT (link) = NULL_TREE;
     }
index 630e262183f058cb55b65a24e51761bfadfff787..fba06619cfbbfc03d84f0bab8f82c337a2ff74f5 100644 (file)
@@ -3547,7 +3547,7 @@ reparse_absdcl_as_expr (type, decl)
     return build_functional_cast (type, NULL_TREE);
 
   /* recurse */
-  decl = reparse_decl_as_expr (type, TREE_OPERAND (decl, 0));
+  decl = reparse_absdcl_as_expr (type, TREE_OPERAND (decl, 0));
 
   decl = build_x_function_call (decl, NULL_TREE, current_class_ref);
 
@@ -3770,11 +3770,28 @@ build_expr_from_tree (t)
             TREE_OPERAND (ref, 1),
             build_expr_from_tree (TREE_OPERAND (t, 2)));
        }
-      return build_method_call
-       (build_expr_from_tree (TREE_OPERAND (t, 1)),
-        TREE_OPERAND (t, 0),
-        build_expr_from_tree (TREE_OPERAND (t, 2)),
-        NULL_TREE, LOOKUP_NORMAL);
+      else 
+       {
+         tree fn = TREE_OPERAND (t, 0);
+         
+         /* We can get a TEMPLATE_ID_EXPR here on code like:
+
+              x->f<2>();
+             
+            so we must resolve that.  However, we can also get things
+            like a BIT_NOT_EXPR here, when referring to a destructor,
+            and things like that are not correctly resolved by
+            build_expr_from_tree.  So, just use build_expr_from_tree
+            when we really need it.  */
+         if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+           fn = build_expr_from_tree (fn);
+
+         return build_method_call
+           (build_expr_from_tree (TREE_OPERAND (t, 1)),
+            fn,
+            build_expr_from_tree (TREE_OPERAND (t, 2)),
+            NULL_TREE, LOOKUP_NORMAL);
+       }
 
     case CALL_EXPR:
       if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
index bdf85dd760f174447793eb2c66630ace2a1412c3..ece3f29c8410d32370e2efafa447a149dce82c21 100644 (file)
@@ -2710,9 +2710,6 @@ convert_nontype_argument (type, expr)
 
     case RECORD_TYPE:
       {
-       tree fns;
-       tree fn;
-
        if (!TYPE_PTRMEMFUNC_P (type))
          /* This handles templates like
               template<class T, T t> void f();
@@ -2743,16 +2740,11 @@ convert_nontype_argument (type, expr)
        if (TREE_CODE (expr) != ADDR_EXPR)
          return error_mark_node;
 
-       fns = TREE_OPERAND (expr, 0);
-       
-       fn = instantiate_type (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type)),
-                              fns, 0);
+       expr = instantiate_type (type, expr, 0);
        
-       if (fn == error_mark_node)
+       if (expr == error_mark_node)
          return error_mark_node;
 
-       expr = build_unary_op (ADDR_EXPR, fn, 0);
-       
        my_friendly_assert (same_type_p (type, TREE_TYPE (expr)),
                            0);
        return expr;
@@ -6972,8 +6964,7 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
         deduction.  */
       if (TREE_CODE (*arg) == ARRAY_TYPE)
        *arg = build_pointer_type (TREE_TYPE (*arg));
-      else if (TREE_CODE (*arg) == FUNCTION_TYPE
-         || TREE_CODE (*arg) == METHOD_TYPE)
+      else if (TREE_CODE (*arg) == FUNCTION_TYPE)
        *arg = build_pointer_type (*arg);
       else
        *arg = TYPE_MAIN_VARIANT (*arg);
@@ -7163,6 +7154,11 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
   if (TREE_CODE (arg) == ADDR_EXPR)
     arg = TREE_OPERAND (arg, 0);
 
+  if (TREE_CODE (arg) == COMPONENT_REF)
+    /* Handle `&x' where `x' is some static or non-static member
+       function name.  */
+    arg = TREE_OPERAND (arg, 1);
+
   /* Strip baselink information.  */
   while (TREE_CODE (arg) == TREE_LIST)
     arg = TREE_VALUE (arg);
@@ -7188,6 +7184,8 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
          if (subargs)
            {
              elem = tsubst (TREE_TYPE (fn), subargs, NULL_TREE);
+             if (TREE_CODE (elem) == METHOD_TYPE)
+               elem = build_ptrmemfunc_type (build_pointer_type (elem));
              good += try_one_overload (tparms, targs, tempargs, parm, elem,
                                        strict, sub_strict, explicit_mask);
            }
@@ -7196,9 +7194,14 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
   else if (TREE_CODE (arg) == OVERLOAD)
     {
       for (; arg; arg = OVL_NEXT (arg))
-       good += try_one_overload (tparms, targs, tempargs, parm,
-                                 TREE_TYPE (OVL_CURRENT (arg)),
-                                 strict, sub_strict, explicit_mask);
+       {
+         tree type = TREE_TYPE (OVL_CURRENT (arg));
+         if (TREE_CODE (type) == METHOD_TYPE)
+           type = build_ptrmemfunc_type (build_pointer_type (type));
+         good += try_one_overload (tparms, targs, tempargs, parm,
+                                   type,
+                                   strict, sub_strict, explicit_mask);
+       }
     }
   else
     my_friendly_abort (981006);
index 7660d386217cdf39db6c089c7de53177afc73ba6..8bb750a66172d3d21b295f17c0185fe3833b34fc 100644 (file)
@@ -416,7 +416,7 @@ build_cplus_array_type_1 (elt_type, index_type)
       saveable_obstack = &permanent_obstack;
     }
 
-  if (processing_template_decl
+  if (uses_template_parms (elt_type)
       || uses_template_parms (index_type))
     {
       t = make_node (ARRAY_TYPE);
@@ -1467,15 +1467,20 @@ build_exception_variant (type, raises)
 
   for (; v; v = TYPE_NEXT_VARIANT (v))
     {
+      tree t;
+      tree u;
+
       if (TYPE_QUALS (v) != type_quals)
        continue;
 
-      /* @@ This should do set equality, not exact match.  */
-      if (simple_cst_list_equal (TYPE_RAISES_EXCEPTIONS (v), raises))
-       /* List of exceptions raised matches previously found list.
+      for (t = TYPE_RAISES_EXCEPTIONS (v), u = raises;
+          t != NULL_TREE && u != NULL_TREE;
+          t = TREE_CHAIN (t), u = TREE_CHAIN (v))
+       if (!same_type_p (TREE_VALUE (t), TREE_VALUE (u)))
+         break;
 
-          @@ Nice to free up storage used in consing up the
-          @@ list of exceptions raised.  */
+      if (!t && !u)
+       /* There's a memory leak here; RAISES is not freed.  */
        return v;
     }
 
index 738e7d85825a81ff2b5e6880c31ed3f69c10da03..521315e17e2ee61f6bcdd3474412a1af588b931d 100644 (file)
@@ -3,9 +3,9 @@
 // Posted by Trevor Taylor <ttaylor@powerup.com.au>
 
 template<class T> struct A {
-    void X() throw(T); // gets bogus error - previous decl - XFAIL *-*-*
+    void X() throw(T);
 };
 
 template<class T>
 inline void A<T>::X() 
-throw(T) { } // gets bogus error - different throws - XFAIL *-*-*
+throw(T) { } 
diff --git a/gcc/testsuite/g++.old-deja/g++.ns/crash3.C b/gcc/testsuite/g++.old-deja/g++.ns/crash3.C
new file mode 100644 (file)
index 0000000..842ed09
--- /dev/null
@@ -0,0 +1,10 @@
+// Build don't link:
+
+namespace N {
+  template <class T> struct S;
+};
+
+void f()
+{
+  N::S(); // ERROR - invalid use of template
+}
index 0f5fdcf12ee8a1605b9439c41a9915092b5dcc27..fece8d48c29f1b1577ad63dbb69c0d19e49a7334 100644 (file)
@@ -1,11 +1,9 @@
 // Build don't link:
 
-// crash test - XFAIL *-*-*
-
 // Simplified from bug report by Trevor Taylor <ttaylor@powerup.com.au>
 
 struct T {
-  int operator()(int) { }
+  int operator()(int) { } // ERROR - candidate
 };
 
 int main() {
diff --git a/gcc/testsuite/g++.old-deja/g++.other/lookup8.C b/gcc/testsuite/g++.old-deja/g++.other/lookup8.C
new file mode 100644 (file)
index 0000000..f81572a
--- /dev/null
@@ -0,0 +1,14 @@
+// Build don't link:
+
+struct S {
+  int A;
+  struct A {
+    enum { a = 0 };
+  };
+
+  void f();
+};
+
+void S::f() {
+  A = A::a;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/array2.C b/gcc/testsuite/g++.old-deja/g++.pt/array2.C
new file mode 100644 (file)
index 0000000..6c5810e
--- /dev/null
@@ -0,0 +1,14 @@
+// Build don't link:
+
+template<int N, class C>
+class Bar {};
+
+template<class C>
+class Huh {};
+
+template<int N>
+void foo(const Bar<N,Huh<float[1]> > &x) {}
+
+int main() {
+  foo(Bar<3,Huh<float[1]> >());
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp81.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp81.C
new file mode 100644 (file)
index 0000000..1584f88
--- /dev/null
@@ -0,0 +1,24 @@
+// Build don't link:
+
+template <int i> class a
+{
+public :
+int  k;
+
+template <int j> int f() const { return this->f<j-1>(); }
+
+int g() const { return f<i>(); };
+};
+
+template <>
+template <>
+int a<2>::f<0>() const {
+  return 0;
+}
+
+int main()
+{
+a<2> x;
+return x.g();
+}
+
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/overload11.C b/gcc/testsuite/g++.old-deja/g++.pt/overload11.C
new file mode 100644 (file)
index 0000000..300d91e
--- /dev/null
@@ -0,0 +1,27 @@
+// Build don't run:
+
+template <class T>
+int f(int (*fn)(T))
+{
+  return (*fn)(3);
+}
+
+struct S {
+  static int g(int) { return 1; }
+  static void g();
+
+  int h();
+};
+
+int S::h()
+{
+  return f(&g);
+}
+
+
+int main()
+{
+  S s;
+  if (s.h () != 1)
+    return 1;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ptrmem4.C b/gcc/testsuite/g++.old-deja/g++.pt/ptrmem4.C
new file mode 100644 (file)
index 0000000..139be92
--- /dev/null
@@ -0,0 +1,28 @@
+// Build don't run:
+
+template<class T,class T1>
+int connect_to_method(T* receiver,
+                      int (T1::*method)()) 
+{ 
+  return (receiver->*method)();
+}
+
+class Gtk_Container
+{
+public:
+  int remove_callback() { return 1; }
+  void remove_callback(int);
+  int f();
+};
+
+int Gtk_Container::f() 
+{
+  return connect_to_method(this, &Gtk_Container::remove_callback);
+}
+
+int main()
+{
+  Gtk_Container gc;
+  if (gc.f () != 1)
+    return 1;
+}