diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7c856b4..025defa 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 8dad82d..fdb3557 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 924e3b1..e544dcc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..bf4c079
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/init1.C
@@ -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) {}
+};