79th Cygnus<->FSF merge
authorMike Stump <mrs@gcc.gnu.org>
Mon, 22 Jan 1996 19:49:02 +0000 (19:49 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Mon, 22 Jan 1996 19:49:02 +0000 (19:49 +0000)
From-SVN: r11082

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/parse.y
gcc/cp/search.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c

index 22cb2b3c743eacd9d27d394874ff271876243212..a7fe9fed674ce71d30dacff2a0fc9812b57dd609 100644 (file)
@@ -1,3 +1,60 @@
+Fri Jan 19 18:03:14 1996  Mike Stump  <mrs@cygnus.com>
+
+       * typeck.c (build_component_ref): Handle getting vbase pointers
+       out of complex multiple inheritance better.
+
+Fri Jan 19 16:27:40 1996  Mike Stump  <mrs@cygnus.com>
+
+       * typeck.c (build_object_ref): Make sure we use the real type, not
+       any reference type.
+
+Fri Jan 19 16:01:47 1996  Mike Stump  <mrs@cygnus.com>
+
+       * tree.c (build_exception_variant): Don't create new types if we
+       don't have to, also build new types on the right obstack.
+
+Fri Jan 19 14:09:44 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * decl.c (store_bindings): Split out from push_to_top_level.
+       (push_to_top_level): Call it for b->type_shadowed on class binding
+       levels.
+
+Fri Jan 19 13:53:14 1996  Mike Stump  <mrs@cygnus.com>
+
+       * search.c (expand_upcast_fixups): Fix so that offsets stored in
+       vbase_offsets are always right.  Fixes a problem where virtual base
+       upcasting and downcasting could be wrong during conversions on this
+       during virtual function dispatch at ctor/dtor time when dynamic
+       vtable fixups for deltas are needed.  This only sounds easier than
+       it is.  :-)
+       (fixup_virtual_upcast_offsets): Change to reflect new calling
+       convention for expand_upcast_fixups.
+
+Fri Jan 19 12:23:08 1996  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * decl2.c (grokbitfield): Strip the NOPs from WIDTH before we
+       check that it's usable as the bitfield width.
+
+Wed Jan 17 21:22:40 1996  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * decl2.c (grokfield): Call cplus_decl_attributes with the attrlist.
+       Pass a null tree to grokdeclarator for its ATTRLIST arg, since it's
+       only ever used for functions in it.
+
+Wed Jan 17 12:10:38 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * parse.y (qualified_type_name): Use the TYPE_DECL, not the type.
+       (nested_type): Ditto.
+       (nested_name_specifier): Use lastiddecl.
+
+       * decl.c (grokdeclarator): Adjust accordingly.
+       * init.c (expand_member_init): Ditto.
+       * parse.y (base_class): Ditto.
+       * typeck2.c (build_functional_cast): Ditto.
+
+       * typeck2.c (build_functional_cast): Fill in name after we've
+       checked for non-aggr type.
+
 Wed Jan 17 10:18:01 1996  Mike Stump  <mrs@cygnus.com>
 
        * decl2.c (warn_pointer_arith): Default to on.
@@ -53,9 +110,6 @@ Mon Jan 15 16:19:32 1996  Jason Merrill  <jason@yorick.cygnus.com>
        * init.c (sort_base_init): Ditto.
        (expand_member_init): Ditto.
        * init.c (is_aggr_type): New function, like is_aggr_typedef.
-       * class.c (pushclass): If !modify and
-       CLASSTYPE_LOCAL_TYPEDECLS (type)), do set up IDENTIFIER_TYPE_VALUE
-       for inherited types.
 
 Mon Jan 15 08:45:01 1996  Jeffrey A Law  (law@cygnus.com)
 
index cca35da334d4fb26059c16a65f413508cdb64e05..87dc9c066dd1118ad75d278adbfa15d2ebb0b546 100644 (file)
@@ -4416,7 +4416,7 @@ pushclass (type, modify)
       else if (type != previous_class_type || current_class_depth > 1)
        {
          build_mi_matrix (type);
-         push_class_decls (type, !modify);
+         push_class_decls (type);
          free_mi_matrix ();
          if (current_class_depth == 1)
            previous_class_type = type;
@@ -4453,12 +4453,6 @@ pushclass (type, modify)
 
       current_function_decl = this_fndecl;
     }
-  else if (CLASSTYPE_LOCAL_TYPEDECLS (type))
-    {
-      build_mi_matrix (type);
-      push_class_decls (type, !modify);
-      free_mi_matrix ();
-    }
 
   if (flag_cadillac)
     cadillac_push_class (type);
index 6ad5ea097daf5e3fac8bbb9ff83713a1b066466d..b4b55b83f704ff3de61e80b345594d9d39c3c2ea 100644 (file)
@@ -2332,7 +2332,7 @@ extern void build_mi_virtuals                     PROTO((int, int));
 extern void add_mi_virtuals                    PROTO((int, tree));
 extern void report_ambiguous_mi_virtuals       PROTO((int, tree));
 extern void note_debug_info_needed             PROTO((tree));
-extern void push_class_decls                   PROTO((tree, int));
+extern void push_class_decls                   PROTO((tree));
 extern void pop_class_decls                    PROTO((tree));
 extern void unuse_fields                       PROTO((tree));
 extern void unmark_finished_struct             PROTO((tree));
index 49eb67ea4be7ebec74ef3a654b09492d9446a813..de18522e2c2e3fcfa22bdd0f8d0189df8cb33c1c 100644 (file)
@@ -1832,6 +1832,48 @@ struct saved_scope {
 static struct saved_scope *current_saved_scope;
 extern tree prev_class_type;
 
+tree
+store_bindings (names, old_bindings)
+     tree names, old_bindings;
+{
+  tree t;
+  for (t = names; t; t = TREE_CHAIN (t))
+    {
+      tree binding, t1, id;
+
+      if (TREE_CODE (t) == TREE_LIST)
+       id = TREE_PURPOSE (t);
+      else
+       id = DECL_NAME (t);
+
+      if (!id
+         || (!IDENTIFIER_LOCAL_VALUE (id)
+             && !IDENTIFIER_CLASS_VALUE (id)))
+       continue;
+
+      for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1))
+       if (TREE_VEC_ELT (t1, 0) == id)
+         goto skip_it;
+           
+      binding = make_tree_vec (4);
+      if (id)
+       {
+         my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
+         TREE_VEC_ELT (binding, 0) = id;
+         TREE_VEC_ELT (binding, 1) = IDENTIFIER_TYPE_VALUE (id);
+         TREE_VEC_ELT (binding, 2) = IDENTIFIER_LOCAL_VALUE (id);
+         TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
+         IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE;
+         IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
+       }
+      TREE_CHAIN (binding) = old_bindings;
+      old_bindings = binding;
+    skip_it:
+      ;
+    }
+  return old_bindings;
+}
+
 void
 push_to_top_level ()
 {
@@ -1849,37 +1891,13 @@ push_to_top_level ()
 
       if (b == global_binding_level)
        continue;
-      
-      for (t = b->names; t; t = TREE_CHAIN (t))
-       {
-         tree binding, t1, t2 = t;
-         tree id = DECL_ASSEMBLER_NAME (t2);
 
-         if (!id
-             || (!IDENTIFIER_LOCAL_VALUE (id)
-                 && !IDENTIFIER_CLASS_VALUE (id)))
-           continue;
+      old_bindings = store_bindings (b->names, old_bindings);
+      /* We also need to check type_shadowed to save class-level type
+        bindings, since pushclass doesn't fill in b->names.  */
+      if (b->parm_flag == 2)
+       old_bindings = store_bindings (b->type_shadowed, old_bindings);
 
-         for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1))
-           if (TREE_VEC_ELT (t1, 0) == id)
-             goto skip_it;
-           
-         binding = make_tree_vec (4);
-         if (id)
-           {
-             my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
-             TREE_VEC_ELT (binding, 0) = id;
-             TREE_VEC_ELT (binding, 1) = IDENTIFIER_TYPE_VALUE (id);
-             TREE_VEC_ELT (binding, 2) = IDENTIFIER_LOCAL_VALUE (id);
-             TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
-             IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE;
-             IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
-           }
-         TREE_CHAIN (binding) = old_bindings;
-         old_bindings = binding;
-       skip_it:
-         ;
-       }
       /* Unwind type-value slots back to top level.  */
       for (t = b->type_shadowed; t; t = TREE_CHAIN (t))
        SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t));
@@ -7783,7 +7801,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
            innermost_code = TREE_CODE (decl);
            if (decl_context == FIELD && ctype == NULL_TREE)
              ctype = current_class_type;
-           if (ctype && TREE_OPERAND (decl, 0) == ctype)
+           if (ctype
+               && (TREE_CODE (TREE_OPERAND (decl, 0)) == TYPE_DECL
+                   && ((DECL_NAME (TREE_OPERAND (decl, 0))
+                        == constructor_name_full (ctype))
+                       || (DECL_NAME (TREE_OPERAND (decl, 0))
+                           == constructor_name (ctype)))))
              TREE_OPERAND (decl, 0) = constructor_name (ctype);
            next = &TREE_OPERAND (decl, 0);
            decl = *next;
@@ -7886,23 +7909,26 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
            next = 0;
            break;
 
+         case TYPE_DECL:
+           /* Parse error puts this typespec where
+              a declarator should go.  */
+           cp_error ("`%T' specified as declarator-id", DECL_NAME (decl));
+           if (TREE_TYPE (decl) == current_class_type)
+             cp_error ("  perhaps you want `%T' for a constructor",
+                       current_class_name);
+           dname = DECL_NAME (decl);
+           name = IDENTIFIER_POINTER (dname);
+
+           /* Avoid giving two errors for this. */
+           IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE;
+
+           declspecs = temp_tree_cons (NULL_TREE, integer_type_node,
+                                       declspecs);
+           *next = dname;
+           next = 0;
+           break;
+
          default:
-           if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't')
-             {
-               /* Parse error puts this typespec where
-                  a declarator should go.  */
-               error ("typename specified as declarator-id");
-               if (current_class_type)
-                 cp_error ("  perhaps you want `%T' for a constructor",
-                           current_class_name);
-               dname = TYPE_IDENTIFIER (decl);
-               name = dname ? IDENTIFIER_POINTER (dname) : "<nameless>";
-               declspecs = temp_tree_cons (NULL_TREE, integer_type_node,
-                                           declspecs);
-               *next = dname;
-               next = 0;
-               break;
-             }
            cp_compiler_error ("`%D' as declarator", decl);
            return 0; /* We used to do a 155 abort here.  */
          }
@@ -8031,6 +8057,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
                }
            }
        }
+      /* C++ aggregate types. */
+      else if (TREE_CODE (id) == TYPE_DECL)
+       {
+         if (type)
+           cp_error ("multiple declarations `%T' and `%T'", type,
+                     TREE_TYPE (id));
+         else
+           type = TREE_TYPE (id);
+         goto found;
+       }
       if (type)
        error ("two or more data types in declaration of `%s'", name);
       else if (TREE_CODE (id) == IDENTIFIER_NODE)
index 03b8ff9662164a38134fd07c358191d1abd2ad90..27f83b0c671f581e48db5a6bfcfc834dffd0dc89 100644 (file)
@@ -1362,7 +1362,7 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
        init = NULL_TREE;
 
   value = grokdeclarator (declarator, declspecs, FIELD, init != 0,
-                         raises, attrlist);
+                         raises, NULL_TREE);
   if (! value)
     return value; /* friend or constructor went bad.  */
 
@@ -1476,6 +1476,10 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
   /* The corresponding pop_obstacks is in cp_finish_decl.  */
   push_obstacks_nochange ();
 
+  if (attrlist)
+    cplus_decl_attributes (value, TREE_PURPOSE (attrlist),
+                          TREE_VALUE (attrlist));
+
   if (TREE_CODE (value) == VAR_DECL)
     {
       /* We cannot call pushdecl here, because that would
@@ -1616,6 +1620,9 @@ grokbitfield (declarator, declspecs, width)
 
   if (width != error_mark_node)
     {
+      /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs.  */
+      STRIP_NOPS (width);
+
       /* detect invalid field size.  */
       if (TREE_CODE (width) == CONST_DECL)
        width = DECL_INITIAL (width);
index e114414b55e9e02e9704db7c0dc2abe403d73301..d10fb162be31c00dcc0072d644f39cefb253cd6a 100644 (file)
@@ -930,10 +930,10 @@ expand_member_init (exp, name, init)
 
   type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
 
-  if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
+  if (TREE_CODE (name) == TYPE_DECL)
     {
-      basetype = name;
-      name = TYPE_IDENTIFIER (name);
+      basetype = TREE_TYPE (name);
+      name = DECL_NAME (name);
     }
 
   if (name == NULL_TREE && IS_AGGR_TYPE (type))
index e3c2607ef11c018dfdab12c36df007bde0da1f1b..b3c8edcd985911cb6f53f3d2a453a44657d2006b 100644 (file)
@@ -2349,7 +2349,7 @@ base_class_list:
 base_class:
          base_class.1
                {
-                 tree type = $1;
+                 tree type = TREE_TYPE ($1);
                  if (! is_aggr_type (type, 1))
                    $$ = NULL_TREE;
                  else if (current_aggr == signature_type_node
@@ -2362,7 +2362,7 @@ base_class:
                    {
                      sorry ("signature inheritance, base type `%s' ignored",
                             IDENTIFIER_POINTER ($$));
-                     $$ = build_tree_list (access_public_node, $$);
+                     $$ = build_tree_list (access_public_node, type);
                    }
                  else if (type && IS_SIGNATURE (type))
                    {
@@ -2370,11 +2370,11 @@ base_class:
                      $$ = NULL_TREE;
                    }
                  else
-                   $$ = build_tree_list (access_default_node, $$);
+                   $$ = build_tree_list (access_default_node, type);
                }
        | base_class_access_list see_typename base_class.1
                {
-                 tree type = $3;
+                 tree type = TREE_TYPE ($3);
                  if (current_aggr == signature_type_node)
                    error ("access and source specifiers not allowed in signature");
                  if (! IS_AGGR_TYPE (type))
@@ -2389,7 +2389,7 @@ base_class:
                    {
                      sorry ("signature inheritance, base type `%s' ignored",
                             IDENTIFIER_POINTER ($$));
-                     $$ = build_tree_list (access_public_node, $3);
+                     $$ = build_tree_list (access_public_node, type);
                    }
                  else if (type && IS_SIGNATURE (type))
                    {
@@ -2397,7 +2397,7 @@ base_class:
                      $$ = NULL_TREE;
                    }
                  else
-                   $$ = build_tree_list ($$, $3);
+                   $$ = build_tree_list ($$, type);
                }
        ;
 
@@ -2857,20 +2857,25 @@ after_type_declarator:
 qualified_type_name:
          type_name %prec EMPTY
                {
-                 $$ = TREE_TYPE ($1);
+                 $$ = identifier_typedecl_value ($1);
                  /* Remember that this name has been used in the class
                     definition, as per [class.scope0] */
                  if (current_class_type
                      && TYPE_BEING_DEFINED (current_class_type)
+                     && ! IDENTIFIER_TEMPLATE ($1)
                      && ! IDENTIFIER_CLASS_VALUE ($1))
-                   pushdecl_class_level (lookup_name ($1, -2));
+                   {
+                     /* Be sure to get an inherited typedef.  */
+                     $$ = lookup_name ($1, 1);
+                     pushdecl_class_level ($$);
+                   }
                }
        | nested_type
        ;
 
 nested_type:
        nested_name_specifier type_name %prec EMPTY
-               { $$ = TREE_TYPE ($2); }
+               { $$ = identifier_typedecl_value ($2); }
        ;
 
 direct_after_type_declarator:
@@ -2984,7 +2989,17 @@ nested_name_specifier:
    inline here?!?  (jason) */
 nested_name_specifier_1:
          TYPENAME SCOPE
-               { got_scope = $$ = TREE_TYPE ($1); }
+               {
+                 $$ = lastiddecl;
+                 /* Remember that this name has been used in the class
+                    definition, as per [class.scope0] */
+                 if (current_class_type
+                     && TYPE_BEING_DEFINED (current_class_type)
+                     && ! TREE_MANGLED ($1)
+                     && ! IDENTIFIER_CLASS_VALUE ($1))
+                   pushdecl_class_level ($$);
+                 got_scope = $$ = TREE_TYPE ($$);
+               }
        | NSNAME SCOPE
                { got_scope = $$ = $1; }
        | template_type SCOPE
index 110eaed978591a2d69fc590aadd25f2214e190c4..208cc0a2adb146b30866df85bda58e050d04dac4 100644 (file)
@@ -2663,7 +2663,10 @@ virtual_context (fndecl, t, vbase)
    they may upcast into a direct base, or
    they may upcast into a different vbase.
 
-   We only need to do fixups in case 2 and 3.
+   We only need to do fixups in case 2 and 3.  In case 2, we add in
+   the virtual base offset to effect an upcast, in case 3, we add in
+   the virtual base offset to effect an upcast, then subtract out the
+   offset for the other virtual base, to effect a downcast into it.
 
    This routine mirrors fixup_vtable_deltas in functionality, though
    this one is runtime based, and the other is compile time based.
@@ -2671,10 +2674,14 @@ virtual_context (fndecl, t, vbase)
    done at runtime.
 
    VBASE_OFFSETS is an association list of virtual bases that contains
-   offset information, so the offsets are only calculated once.  */
+   offset information for the virtual bases, so the offsets are only
+   calculated once.  The offsets are computed by where we think the
+   vbase should be (as noted by the CLASSTYPE_SEARCH_SLOT) minus where
+   the vbase really is. */
 static void
-expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
-     tree binfo, addr, orig_addr, vbase, t, *vbase_offsets;
+expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
+                     vbase_offsets)
+     tree binfo, addr, orig_addr, vbase, vbase_addr, t, *vbase_offsets;
 {
   tree virtuals = BINFO_VIRTUALS (binfo);
   tree vc;
@@ -2685,7 +2692,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
   if (! delta)
     {
       delta = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbase));
-      delta = build (MINUS_EXPR, ptrdiff_type_node, delta, addr);
+      delta = build (MINUS_EXPR, ptrdiff_type_node, delta, vbase_addr);
       delta = save_expr (delta);
       delta = tree_cons (vbase, delta, *vbase_offsets);
       *vbase_offsets = delta;
@@ -2739,26 +2746,32 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
          naref = build_array_ref (nvtbl, idx);
          old_delta = build_component_ref (aref, delta_identifier, 0, 0);
          new_delta = build_component_ref (naref, delta_identifier, 0, 0);
+
+         /* This is a upcast, so we have to add the offset for the
+            virtual base.  */
          old_delta = build_binary_op (PLUS_EXPR, old_delta,
                                       TREE_VALUE (delta), 0);
          if (vc)
            {
-             /* If this is set, we need to add in delta adjustments for
-                the other virtual base.  */
+             /* If this is set, we need to subtract out the delta
+                adjustments for the other virtual base that we
+                downcast into.  */
              tree vc_delta = purpose_member (vc, *vbase_offsets);
              if (! vc_delta)
                {
                  tree vc_addr = convert_pointer_to_real (vc, orig_addr);
                  vc_delta = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vc));
                  vc_delta = build (MINUS_EXPR, ptrdiff_type_node,
-                                   vc_addr, vc_delta);
+                                   vc_delta, vc_addr);
                  vc_delta = save_expr (vc_delta);
                  *vbase_offsets = tree_cons (vc, vc_delta, *vbase_offsets);
                }
              else
                vc_delta = TREE_VALUE (vc_delta);
    
-             old_delta = build_binary_op (PLUS_EXPR, old_delta, vc_delta, 0);
+             /* This is a downcast, so we have to subtract the offset
+                for the virtual base.  */
+             old_delta = build_binary_op (MINUS_EXPR, old_delta, vc_delta, 0);
            }
 
          TREE_READONLY (new_delta) = 0;
@@ -2800,8 +2813,9 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
   /* Should we use something besides CLASSTYPE_VFIELDS? */
   if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo)))
     {
-      addr = convert_pointer_to_real (binfo, addr);
-      expand_upcast_fixups (real_binfo, addr, orig_addr, vbase, type, vbase_offsets);
+      tree new_addr = convert_pointer_to_real (binfo, addr);
+      expand_upcast_fixups (real_binfo, new_addr, orig_addr, vbase, addr,
+                           type, vbase_offsets);
     }
 }
 
@@ -3334,14 +3348,10 @@ dfs_compress_decls (binfo)
    lattice.  Where ambiguities result, we mark them
    with `error_mark_node' so that if they are encountered
    without explicit qualification, we can emit an error
-   message.
-
-   ONLY_TYPES is set when defining TYPE so that inherited types are visible
-   in the derived class.  */
+   message.  */
 void
-push_class_decls (type, only_types)
+push_class_decls (type)
      tree type;
-     int only_types;
 {
   tree id;
   struct obstack *ambient_obstack = current_obstack;
@@ -3396,12 +3406,7 @@ push_class_decls (type, only_types)
       /* Install the original class value in order to make
         pushdecl_class_level work correctly.  */
       IDENTIFIER_CLASS_VALUE (id) = TREE_VALUE (closed_envelopes);
-      if (only_types)
-       {
-         if (TREE_CODE (new) == TYPE_DECL)
-           set_identifier_type_value (id, TREE_TYPE (new));
-       } 
-      else if (TREE_CODE (new) == TREE_LIST)
+      if (TREE_CODE (new) == TREE_LIST)
        push_class_level_binding (id, new);
       else
        pushdecl_class_level (new);
index be0fc99195b78eed5ce47252d61506bd9b2bbc3c..d0f27f953485da9455ae0649d51765cf354178df 100644 (file)
@@ -1579,7 +1579,7 @@ build_exception_variant (type, raises)
   int constp = TYPE_READONLY (type);
   int volatilep = TYPE_VOLATILE (type);
 
-  for (v = TYPE_NEXT_VARIANT (v); v; v = TYPE_NEXT_VARIANT (v))
+  for (; v; v = TYPE_NEXT_VARIANT (v))
     {
       if (TYPE_READONLY (v) != constp
          || TYPE_VOLATILE (v) != volatilep)
@@ -1595,9 +1595,8 @@ build_exception_variant (type, raises)
     }
 
   /* Need to build a new variant.  */
-  v = copy_node (type);
-  TYPE_NEXT_VARIANT (v) = TYPE_NEXT_VARIANT (type);
-  TYPE_NEXT_VARIANT (type) = v;
+  v = build_type_copy (type);
+
   if (raises && ! TREE_PERMANENT (raises))
     {
       push_obstacks_nochange ();
index 9901080192a3a19af1c7219c89662214d360357e..9e5f4e657a59c73adbfbdaef7ed3f81ec071a137 100644 (file)
@@ -1539,7 +1539,7 @@ build_object_ref (datum, basetype, field)
     }
   else if (is_aggr_type (basetype, 1))
     {
-      tree binfo = binfo_or_else (basetype, TREE_TYPE (datum));
+      tree binfo = binfo_or_else (basetype, dtype);
       if (binfo)
        return build_component_ref (build_scoped_ref (datum, basetype),
                                    field, binfo, 1);
@@ -1825,7 +1825,16 @@ build_component_ref (datum, component, basetype_path, protect)
          error ("invalid reference to NULL ptr, use ptr-to-member instead");
          return error_mark_node;
        }
-      addr = convert_pointer_to (DECL_FIELD_CONTEXT (field), addr);
+      if (VBASE_NAME_P (DECL_NAME (field)))
+         {
+           /* It doesn't matter which vbase pointer we grab, just
+              find one of them.  */
+           tree binfo = get_binfo (DECL_FIELD_CONTEXT (field),
+                                   TREE_TYPE (TREE_TYPE (addr)), 0);
+           addr = convert_pointer_to_real (binfo, addr);
+         }
+       else
+         addr = convert_pointer_to (DECL_FIELD_CONTEXT (field), addr);
       datum = build_indirect_ref (addr, NULL_PTR);
       my_friendly_assert (datum != error_mark_node, 311);
     }
@@ -5831,7 +5840,7 @@ build_modify_expr (lhs, modifycode, rhs)
       if (build_default_binary_type_conversion (modifycode, &lhs_tmp, &rhs_tmp))
        {
          lhs = stabilize_reference (lhs_tmp);
-         /* Forget is was ever anything else.  */
+         /* Forget it was ever anything else.  */
          olhstype = lhstype = TREE_TYPE (lhs);
          newrhs = build_binary_op (modifycode, lhs, rhs_tmp, 1);
        }
index a2f81729cadc547771fcf0e80fe8e496fb8023b0..69d003d916c080fc89f6c338a71e3d7bf3d72c2b 100644 (file)
@@ -1440,6 +1440,8 @@ build_functional_cast (exp, parms)
          type = TREE_TYPE (type);
        }
     }
+  else if (TREE_CODE (exp) == TYPE_DECL)
+    type = TREE_TYPE (exp);
   else
     type = exp;
 
@@ -1449,20 +1451,6 @@ build_functional_cast (exp, parms)
       return error_mark_node;
     }
 
-  /* Prepare to evaluate as a call to a constructor.  If this expression
-     is actually used, for example,
-        
-     return X (arg1, arg2, ...);
-        
-     then the slot being initialized will be filled in.  */
-
-  if (name == NULL_TREE)
-    {
-      name = TYPE_NAME (type);
-      if (TREE_CODE (name) == TYPE_DECL)
-       name = DECL_NESTED_TYPENAME (name);
-    }
-
   if (! IS_AGGR_TYPE (type))
     {
       /* this must build a C cast */
@@ -1478,6 +1466,20 @@ build_functional_cast (exp, parms)
       return build_c_cast (type, parms, 1);
     }
 
+  /* Prepare to evaluate as a call to a constructor.  If this expression
+     is actually used, for example,
+        
+     return X (arg1, arg2, ...);
+        
+     then the slot being initialized will be filled in.  */
+
+  if (name == NULL_TREE)
+    {
+      name = TYPE_NAME (type);
+      if (TREE_CODE (name) == TYPE_DECL)
+       name = DECL_NESTED_TYPENAME (name);
+    }
+
   if (TYPE_SIZE (type) == NULL_TREE)
     {
       cp_error ("type `%T' is not yet defined", type);