re PR c++/525 (Problem with Multiple Inheritance and -pedantic)
authorJason Merrill <jason@redhat.com>
Sat, 6 Apr 2002 16:15:20 +0000 (11:15 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Sat, 6 Apr 2002 16:15:20 +0000 (11:15 -0500)
        PR c++/525
        * init.c (build_member_call): Use build_scoped_ref.
        (resolve_offset_ref): Likewise.
        * call.c (build_scoped_method_call): Likewise.
        * tree.c (maybe_dummy_object): Kludge around current_class_type being
        wrong.
        * typeck2.c (build_scoped_ref): Return the binfo via binfo_p parm.
        * cp-tree.h: Adjust.

        * init.c (push_base_cleanups): Just use build_scoped_method_call.

From-SVN: r51956

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/testsuite/g++.dg/lookup/disamb1.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.jason/access8.C

index 6f2a6ab..524cbea 100644 (file)
@@ -1,5 +1,16 @@
 2002-04-06  Jason Merrill  <jason@redhat.com>
 
+       PR c++/525
+       * init.c (build_member_call): Use build_scoped_ref.
+       (resolve_offset_ref): Likewise.
+       * call.c (build_scoped_method_call): Likewise.
+       * tree.c (maybe_dummy_object): Kludge around current_class_type being 
+       wrong.
+       * typeck2.c (build_scoped_ref): Return the binfo via binfo_p parm.
+       * cp-tree.h: Adjust.
+       
+       * init.c (push_base_cleanups): Just use build_scoped_method_call.
+
        PR c++/6179
        * method.c (implicitly_declare_fn): Pass unqualified type to 
        synthesize_exception_spec.
index 1a74f74..d341fb0 100644 (file)
@@ -298,27 +298,10 @@ build_scoped_method_call (exp, basetype, name, parms)
       return error_mark_node;
     }
 
-  if (! binfo)
-    {
-      binfo = lookup_base (type, basetype, ba_check, NULL);
-      if (binfo == error_mark_node)
-       return error_mark_node;
-      if (! binfo)
-       error_not_base_type (basetype, type);
-    }
+  decl = build_scoped_ref (exp, basetype, &binfo);
 
   if (binfo)
     {
-      if (TREE_CODE (exp) == INDIRECT_REF)
-       {
-         decl = build_base_path (PLUS_EXPR,
-                                 build_unary_op (ADDR_EXPR, exp, 0),
-                                 binfo, 1);
-         decl = build_indirect_ref (decl, NULL);
-       }
-      else
-       decl = build_scoped_ref (exp, basetype);
-
       /* Call to a destructor.  */
       if (TREE_CODE (name) == BIT_NOT_EXPR)
        {
index b65467b..8b3a256 100644 (file)
@@ -4387,7 +4387,7 @@ extern int abstract_virtuals_error                PARAMS ((tree, tree));
 
 extern tree store_init_value                   PARAMS ((tree, tree));
 extern tree digest_init                                PARAMS ((tree, tree, tree *));
-extern tree build_scoped_ref                   PARAMS ((tree, tree));
+extern tree build_scoped_ref                   PARAMS ((tree, tree, tree *));
 extern tree build_x_arrow                      PARAMS ((tree));
 extern tree build_m_component_ref              PARAMS ((tree, tree));
 extern tree build_functional_cast              PARAMS ((tree, tree));
index 57b3dba..5caa69c 100644 (file)
@@ -1496,20 +1496,13 @@ build_member_call (type, name, parmlist)
   decl = maybe_dummy_object (type, &basetype_path);
 
   /* Convert 'this' to the specified type to disambiguate conversion
-     to the function's context.  Apparently Standard C++ says that we
-     shouldn't do this.  */
-  if (decl == current_class_ref
-      && ! pedantic
-      && ACCESSIBLY_UNIQUELY_DERIVED_P (type, current_class_type))
-    {
-      tree olddecl = current_class_ptr;
-      tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));
-      if (oldtype != type)
-       {
-         tree newtype = build_qualified_type (type, TYPE_QUALS (oldtype));
-         decl = convert_force (build_pointer_type (newtype), olddecl, 0);
-         decl = build_indirect_ref (decl, NULL);
-       }
+     to the function's context.  */
+  if (decl == current_class_ref)
+    {
+      basetype_path = NULL_TREE;
+      decl = build_scoped_ref (decl, type, &basetype_path);
+      if (decl == error_mark_node)
+       return error_mark_node;
     }
 
   if (method_name == constructor_name (type)
@@ -1819,7 +1812,7 @@ resolve_offset_ref (exp)
   if (TREE_CODE (member) == FIELD_DECL
       && (base == current_class_ref || is_dummy_object (base)))
     {
-      tree binfo = TYPE_BINFO (current_class_type);
+      tree binfo = NULL_TREE;
 
       /* Try to get to basetype from 'this'; if that doesn't work,
          nothing will.  */
@@ -1827,13 +1820,7 @@ resolve_offset_ref (exp)
 
       /* First convert to the intermediate base specified, if appropriate.  */
       if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
-       {
-         binfo = binfo_or_else (TYPE_OFFSET_BASETYPE (type),
-                                current_class_type);
-         if (!binfo)
-           return error_mark_node;
-         base = build_base_path (PLUS_EXPR, base, binfo, 1);
-       }
+       base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type), &binfo);
 
       return build_component_ref (base, member, binfo, 1);
     }
@@ -3225,7 +3212,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
 /* At the beginning of a destructor, push cleanups that will call the
    destructors for our base classes and members.
 
-   Called from setup_vtbl_ptr.  */
+   Called from begin_destructor_body.  */
 
 void
 push_base_cleanups ()
@@ -3255,21 +3242,9 @@ push_base_cleanups ()
 
          if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
            {
-             tree base_ptr_type = build_pointer_type (base_type);
-             expr = current_class_ptr;
-                 
-             /* Convert to the basetype here, as we know the layout is
-                fixed. What is more, if we let build_method_call do it,
-                it will use the vtable, which may have been clobbered
-                by the deletion of our primary base.  */
-                  
-             expr = build1 (NOP_EXPR, base_ptr_type, expr);
-             expr = build (PLUS_EXPR, base_ptr_type, expr,
-                           BINFO_OFFSET (vbase));
-             expr = build_indirect_ref (expr, NULL);
-             expr = build_method_call (expr, base_dtor_identifier,
-                                       NULL_TREE, vbase,
-                                       LOOKUP_NORMAL);
+             expr = build_scoped_method_call (current_class_ref, vbase,
+                                              base_dtor_identifier,
+                                              NULL_TREE);
              expr = build (COND_EXPR, void_type_node, cond,
                            expr, void_zero_node);
              finish_decl_cleanup (NULL_TREE, expr);
index b705783..30a6ddb 100644 (file)
@@ -5559,7 +5559,11 @@ tsubst_default_argument (fn, type, arg)
        };
      
      we must be careful to do name lookup in the scope of S<T>,
-     rather than in the current class.  */
+     rather than in the current class.
+
+     ??? current_class_type affects a lot more than name lookup.  This is
+     very fragile.  Fortunately, it will go away when we do 2-phase name
+     binding properly.  */
   if (DECL_CLASS_SCOPE_P (fn))
     pushclass (DECL_CONTEXT (fn), 2);
 
index e0f7361..641d82b 100644 (file)
@@ -1844,7 +1844,11 @@ maybe_dummy_object (type, binfop)
   if (binfop)
     *binfop = binfo;
   
-  if (current_class_ref && context == current_class_type)
+  if (current_class_ref && context == current_class_type
+      // Kludge: Make sure that current_class_type is actually correct.
+      // It might not be if we're in the middle of tsubst_default_argument.
+      && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)),
+                     current_class_type))
     decl = current_class_ref;
   else
     decl = build_dummy_object (context);
index 593e2bb..be07b2e 100644 (file)
@@ -1826,10 +1826,9 @@ build_object_ref (datum, basetype, field)
     }
   else if (is_aggr_type (basetype, 1))
     {
-      tree binfo = binfo_or_else (basetype, dtype);
-      if (binfo)
-       return build_x_component_ref (build_scoped_ref (datum, basetype),
-                                     field, binfo, 1);
+      tree binfo = NULL_TREE;
+      datum = build_scoped_ref (datum, basetype, &binfo);
+      return build_x_component_ref (datum, field, binfo, 1);
     }
   return error_mark_node;
 }
index 48caade..d7ac3d7 100644 (file)
@@ -954,7 +954,7 @@ process_init_constructor (type, init, elts)
 \f
 /* Given a structure or union value DATUM, construct and return
    the structure or union component which results from narrowing
-   that value by the type specified in BASETYPE.  For example, given the
+   that value to the base specified in BASETYPE.  For example, given the
    hierarchy
 
    class L { int ii; };
@@ -975,29 +975,36 @@ process_init_constructor (type, init, elts)
    I used to think that this was nonconformant, that the standard specified
    that first we look up ii in A, then convert x to an L& and pull out the
    ii part.  But in fact, it does say that we convert x to an A&; A here
-   is known as the "naming class".  (jason 2000-12-19) */
+   is known as the "naming class".  (jason 2000-12-19)
+
+   BINFO_P points to a variable initialized either to NULL_TREE or to the
+   binfo for the specific base subobject we want to convert to.  */
 
 tree
-build_scoped_ref (datum, basetype)
+build_scoped_ref (datum, basetype, binfo_p)
      tree datum;
      tree basetype;
+     tree *binfo_p;
 {
-  tree ref;
   tree binfo;
 
   if (datum == error_mark_node)
     return error_mark_node;
-  binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL);
+  if (*binfo_p)
+    binfo = *binfo_p;
+  else
+    binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL);
 
-  if (binfo == error_mark_node)
-    return error_mark_node;
-  if (!binfo)
-    return error_not_base_type (TREE_TYPE (datum), basetype);
-  
-  ref = build_unary_op (ADDR_EXPR, datum, 0);
-  ref = build_base_path (PLUS_EXPR, ref, binfo, 1);
+  if (!binfo || binfo == error_mark_node)
+    {
+      *binfo_p = NULL_TREE;
+      if (!binfo)
+       error_not_base_type (basetype, TREE_TYPE (datum));
+      return error_mark_node;
+    }
 
-  return build_indirect_ref (ref, "(compiler error in build_scoped_ref)");
+  *binfo_p = binfo;
+  return build_base_path (PLUS_EXPR, datum, binfo, 1);
 }
 
 /* Build a reference to an object specified by the C++ `->' operator.
diff --git a/gcc/testsuite/g++.dg/lookup/disamb1.C b/gcc/testsuite/g++.dg/lookup/disamb1.C
new file mode 100644 (file)
index 0000000..8a3be65
--- /dev/null
@@ -0,0 +1,15 @@
+// PR c++/525
+// Bug: With -pedantic, we weren't converting this to D1* for the call.
+
+struct A
+{
+  void f();
+};
+
+struct B1: public A {};
+struct B2: public A {};
+
+struct C: public B1, public B2
+{
+  void g() { B1::f(); };
+};
index c8addcd..91e114a 100644 (file)
@@ -25,5 +25,6 @@ void inh::myf(int i) {
 }
 
 void top_t::myf(int i) {
-        inh::myf(i);
+        inh::myf(i);           // ERROR - cannot convert to inh
+       mel::myf(i);
 }