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) {} +};