re PR c++/3154 (Tree check: expected class 't', have 'd' (type_decl) in is_aggr_type...
authorNathan Sidwell <nathan@codesourcery.com>
Thu, 15 Nov 2001 10:03:41 +0000 (10:03 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Thu, 15 Nov 2001 10:03:41 +0000 (10:03 +0000)
cp:
PR g++/3154
* init.c (sort_base_init): Remove unreachable code.
(expand_member_init): Adjust comment to reflect reality. Simplify
and remove unreachable code.
testsuite:
* g++.dg/other/init1.C: New test.

From-SVN: r47047

gcc/cp/ChangeLog
gcc/cp/init.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/other/init1.C [new file with mode: 0644]

index 7c856b4f1cad6c3788fbefcc8ba935166c92e8ed..025defa26b90d5bba98450a13cc09201c31e1d59 100644 (file)
@@ -1,3 +1,10 @@
+2001-11-15  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR g++/3154
+       * init.c (sort_base_init): Remove unreachable code.
+       (expand_member_init): Adjust comment to reflect reality. Simplify
+       and remove unreachable code.
+
 2001-11-15  Neil Booth  <neil@daikokuya.demon.co.uk>
 
        * cp-tree.h (init_reswords, cxx_init_decl_processing): New.
index 8dad82d071178f2b7a45c04a5657b987b9901f0e..fdb3557d2b104ed261558ec73c0057ab010b7203 100644 (file)
@@ -557,68 +557,39 @@ sort_base_init (t, base_init_list, rbase_ptr, vbase_ptr)
   tree vbases = NULL_TREE;
 
   /* First walk through and splice out vbase and invalid initializers.
-     Also replace names with binfos.  */
+     Also replace types with binfos.  */
 
   last = tree_cons (NULL_TREE, NULL_TREE, base_init_list);
   for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x))
     {
       tree basetype = TREE_PURPOSE (x);
-      tree binfo = NULL_TREE;
+      tree binfo = binfo_or_else (basetype, t);
+      
+      if (binfo == NULL_TREE)
+       /* BASETYPE might be an inaccessible direct base (because it
+          is also an indirect base).  */
+       continue;
 
-      if (basetype == NULL_TREE)
+      if (TREE_VIA_VIRTUAL (binfo))
        {
-         /* Initializer for single base class.  Must not
-            use multiple inheritance or this is ambiguous.  */
-         switch (n_baseclasses)
-           {
-           case 0:
-             cp_error ("`%T' does not have a base class to initialize",
-                       current_class_type);
-             return;
-           case 1:
-             break;
-           default:
-             cp_error ("unnamed initializer ambiguous for `%T' which uses multiple inheritance",
-                       current_class_type);
-             return;
-           }
-         binfo = TREE_VEC_ELT (binfos, 0);
+         /* Virtual base classes are special cases.  Their
+            initializers are recorded with this constructor, and they
+            are used when this constructor is the top-level
+            constructor called.  */
+         tree v = binfo_for_vbase (BINFO_TYPE (binfo), t);
+         vbases = tree_cons (v, TREE_VALUE (x), vbases);
        }
-      else if (is_aggr_type (basetype, 1))
+      else
        {
-         binfo = binfo_or_else (basetype, t);
-         if (binfo == NULL_TREE)
-           continue;
-
-         /* Virtual base classes are special cases.  Their initializers
-            are recorded with this constructor, and they are used when
-            this constructor is the top-level constructor called.  */
-         if (TREE_VIA_VIRTUAL (binfo))
-           {
-             tree v = binfo_for_vbase (BINFO_TYPE (binfo), t);
-             vbases = tree_cons (v, TREE_VALUE (x), vbases);
-             continue;
-           }
-         else
-           {
-             /* Otherwise, if it is not an immediate base class, complain.  */
-             for (i = n_baseclasses-1; i >= 0; i--)
-               if (BINFO_TYPE (binfo) == BINFO_TYPE (TREE_VEC_ELT (binfos, i)))
-                 break;
-             if (i < 0)
-               {
-                 cp_error ("`%T' is not an immediate base class of `%T'",
-                           basetype, current_class_type);
-                 continue;
-               }
-           }
+         /* Otherwise, it must be an immediate base class.  */
+         my_friendly_assert
+           (same_type_p (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
+                         t), 20011113);
+
+         TREE_PURPOSE (x) = binfo;
+         TREE_CHAIN (last) = x;
+         last = x;
        }
-      else
-       my_friendly_abort (365);
-
-      TREE_PURPOSE (x) = binfo;
-      TREE_CHAIN (last) = x;
-      last = x;
     }
   TREE_CHAIN (last) = NULL_TREE;
 
@@ -1039,17 +1010,16 @@ member_init_ok_or_else (field, type, member_name)
   return 1;
 }
 
-/* If NAME is a viable field name for the aggregate DECL,
-   and PARMS is a viable parameter list, then expand an _EXPR
-   which describes this initialization.
-
-   Note that we do not need to chase through the class's base classes
-   to look for NAME, because if it's in that list, it will be handled
-   by the constructor for that base class.
+/* EXP is an expression of aggregate type. NAME is an IDENTIFIER_NODE
+   which names a field, or it is a _TYPE node or TYPE_DECL which names
+   a base for that type.  INIT is a parameter list for that field's or
+   base's constructor.  Check the validity of NAME, and return a
+   TREE_LIST of the base _TYPE or FIELD_DECL and the INIT. EXP is used
+   only to get its type.  If NAME is invalid, return NULL_TREE and
+   issue a diagnostic.
 
-   We do not yet have a fixed-point finder to instantiate types
-   being fed to overloaded constructors.  If there is a unique
-   constructor, then argument types can be got from that one.  */
+   An old style unnamed direct single base construction is permitted,
+   where NAME is NULL.  */
 
 tree
 expand_member_init (exp, name, init)
@@ -1062,72 +1032,56 @@ expand_member_init (exp, name, init)
     return NULL_TREE;
 
   type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+  my_friendly_assert (IS_AGGR_TYPE (type), 20011113);
 
-  if (name && TYPE_P (name))
+  if (!name)
     {
-      basetype = name;
-      name = TYPE_IDENTIFIER (name);
+      /* This is an obsolete unnamed base class initializer.  The
+        parser will already have warned about its use.  */
+      switch (CLASSTYPE_N_BASECLASSES (type))
+       {
+       case 0:
+         cp_error ("unnamed initializer for `%T', which has no base classes",
+                   type);
+         return NULL_TREE;
+       case 1:
+         basetype = TYPE_BINFO_BASETYPE (type, 0);
+         break;
+       default:
+         cp_error ("unnamed initializer for `%T', which uses multiple inheritance",
+                   type);
+         return NULL_TREE;
+      }
     }
-  else if (name && TREE_CODE (name) == TYPE_DECL)
+  else if (TYPE_P (name))
     {
-      basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
-      name = DECL_NAME (name);
+      basetype = name;
+      name = TYPE_NAME (name);
     }
-
-  if (name == NULL_TREE && IS_AGGR_TYPE (type))
-    switch (CLASSTYPE_N_BASECLASSES (type))
-      {
-      case 0:
-       error ("base class initializer specified, but no base class to initialize");
-       return NULL_TREE;
-      case 1:
-       basetype = TYPE_BINFO_BASETYPE (type, 0);
-       break;
-      default:
-       error ("initializer for unnamed base class ambiguous");
-       cp_error ("(type `%T' uses multiple inheritance)", type);
-       return NULL_TREE;
-      }
+  else if (TREE_CODE (name) == TYPE_DECL)
+    basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
 
   my_friendly_assert (init != NULL_TREE, 0);
 
-  /* The grammar should not allow fields which have names that are
-     TYPENAMEs.  Therefore, if the field has a non-NULL TREE_TYPE, we
-     may assume that this is an attempt to initialize a base class
-     member of the current type.  Otherwise, it is an attempt to
-     initialize a member field.  */
-
   if (init == void_type_node)
     init = NULL_TREE;
 
-  if (name == NULL_TREE || basetype)
+  if (basetype)
     {
-      if (name == NULL_TREE)
-       {
-#if 0
-         if (basetype)
-           name = TYPE_IDENTIFIER (basetype);
-         else
-           {
-             error ("no base class to initialize");
-             return;
-           }
-#endif
-       }
-      else if (basetype != type
-              && ! current_template_parms
-              && ! vec_binfo_member (basetype,
-                                     TYPE_BINFO_BASETYPES (type))
-              && ! binfo_for_vbase (basetype, type))
+      if (current_template_parms)
+       ;
+      else if (vec_binfo_member (basetype, TYPE_BINFO_BASETYPES (type)))
+       /* A direct base.  */;
+      else if (binfo_for_vbase (basetype, type))
+       /* A virtual base.  */;
+      else
        {
-         if (IDENTIFIER_CLASS_VALUE (name))
-           goto try_member;
          if (TYPE_USES_VIRTUAL_BASECLASSES (type))
-           cp_error ("type `%T' is not an immediate or virtual basetype for `%T'",
-                     basetype, type);
+           cp_error ("type `%D' is not a direct or virtual base of `%T'",
+                     name, type);
          else
-           cp_error ("type `%T' is not an immediate basetype for `%T'",
-                     basetype, type);
+           cp_error ("type `%D' is not a direct base of `%T'",
+                     name, type);
          return NULL_TREE;
        }
 
@@ -1135,7 +1089,6 @@ expand_member_init (exp, name, init)
     }
   else
     {
-    try_member:
       field = lookup_field (type, name, 1, 0);
 
       if (! member_init_ok_or_else (field, type, name))
index 924e3b1260f65127763faee5a684ca260c7cac84..e544dcc57e8b34e31047247332af76971f89f16f 100644 (file)
@@ -1,3 +1,7 @@
+2001-11-15  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * g++.dg/other/init1.C: New test.
+
 2001-11-14  Geoffrey Keating  <geoffk@redhat.com>
 
        * gcc.dg/noncompile/920923-1.c: xstormy16 produces an extra error
diff --git a/gcc/testsuite/g++.dg/other/init1.C b/gcc/testsuite/g++.dg/other/init1.C
new file mode 100644 (file)
index 0000000..bf4c079
--- /dev/null
@@ -0,0 +1,28 @@
+// { dg-do compile }
+
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 13 Nov 2001 <nathan@codesourcery.com>
+
+// Bug 3154
+
+class A {};
+
+struct B : A
+{
+  typedef A Parent;
+  
+  B () : Parent () {};
+};
+
+class T
+{
+  typedef int Foo;
+  T () : Foo () {}     // { dg-error "type `T::Foo' is not" "" }
+};
+
+struct S : B
+{
+  int Parent;
+
+  S () :Parent (1) {}
+};