diff -u -r gcc-2.95.orig/gcc/c-decl.c gcc-2.95/gcc/c-decl.c --- gcc-2.95.orig/gcc/c-decl.c Fri Oct 1 14:34:10 1999 +++ gcc-2.95/gcc/c-decl.c Sat Oct 2 04:55:07 1999 @@ -591,6 +591,18 @@ int warn_multichar = 1; +/* enable cplusplus features */ + +int flag_cplusplus = 0; /* enables base-inclusion here */ + +/* warn about surprising features */ + +int warn_surprising = 1; /* warns on base-inclusion here */ + +/* warn about struct-casts with different field names */ + +int warn_fieldnames_different = 1; /* make struct-matching care about field-names */ + /* Nonzero means `$' can be in an identifier. */ #ifndef DOLLARS_IN_IDENTIFIERS @@ -692,6 +704,28 @@ flag_no_asm = 0; flag_no_nonansi_builtin = 0; flag_isoc9x = 1; + flag_cplusplus = 1; /*enables inclusion syntax*/ + } + else if (!strcmp (argstart, "gtk2")) + { + flag_traditional = 0; + flag_writable_strings = 0; + flag_no_asm = 0; + flag_no_nonansi_builtin = 0; + flag_isoc9x = 1; + flag_cplusplus = 1; /*enables inclusion syntax*/ + warn_surprising = 0; /*and doesn't warn about its use*/ + } + else if (!strcmp (argstart, "gtk2+")) + { + flag_traditional = 0; + flag_writable_strings = 0; + flag_no_asm = 0; + flag_no_nonansi_builtin = 0; + flag_isoc9x = 1; + flag_cplusplus = 1; /*enables inclusion syntax*/ + warn_surprising = 0; /*doesn't warn about its use*/ + warn_fieldnames_different = 0; /*and doesn't care about misnamings*/ } else error ("unknown C standard `%s'", argstart); @@ -6139,6 +6173,149 @@ return t; } + +char* +get_decl_name (decl) + tree decl; +{ + /* Look inside a declarator for the name being declared + and get it as a string, for an error message. */ + char class; + tree node = decl; + + if (!node) + return "((none))"; + + while (TREE_CODE (node) == ARRAY_REF + || TREE_CODE (node) == INDIRECT_REF + || TREE_CODE (node) == CALL_EXPR ) + { + node = TREE_OPERAND (node, 0); + } + + while (TREE_CODE (node) == POINTER_TYPE) + { + node = TREE_TYPE (node); + } + + if (TREE_CODE (node) == IDENTIFIER_NODE) + return (IDENTIFIER_POINTER (node)); + + class = TREE_CODE_CLASS (TREE_CODE (node)); + + if (DECL_NAME (node) && TREE_CODE(DECL_NAME(node)) == IDENTIFIER_NODE) + return (IDENTIFIER_POINTER (DECL_NAME (node))); + + if (TYPE_NAME (node)) + { + if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE) + return (IDENTIFIER_POINTER (TYPE_NAME (node))); + else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL + && DECL_NAME (TYPE_NAME (node)) + && TREE_CODE(DECL_NAME(TYPE_NAME(node))) == IDENTIFIER_NODE ) + return (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node)))); + } + + return "((unknown))"; +} + +/* Puts markers that help the finish part to identify the base class, + emit some warnings/errors right here before scanning the struct definition */ +tree +start_struct_submorph (code, name, base) + enum tree_code code; + tree name; + tree base; +{ + register tree t; + + if (!flag_cplusplus) + { + error ("base type inclusion feature disabled (in declaration of `%s')", + IDENTIFIER_POINTER(name)); + return start_struct (code, name); + } + + if (warn_surprising) + { + warning ("inclusion syntax used to declare `%s'", IDENTIFIER_POINTER(name)); + } + + t = lookup_tag (code, base, current_binding_level, 0); + if (!t) + { + error ("unknown base type `%s' (in declaration of `%s')", + IDENTIFIER_POINTER (base), IDENTIFIER_POINTER (name)); + return start_struct (code, name); + } + else if (TREE_CODE (t) != code) + { + error ("base type `%s' is no struct (in declaration of `%s')", + IDENTIFIER_POINTER (base), IDENTIFIER_POINTER (name)); + pending_xref_error (); + return start_struct (code, name); + } + else + base = t; + + if (TYPE_SIZE (base) == 0) + { + error ("base type `%s' has incomplete type (in declaration of `%s')", + get_decl_name(base), IDENTIFIER_POINTER (name)); + } + if (C_DECL_VARIABLE_SIZE (base)) + { + warning ("base type `%s' has variable size (in declaration of `%s')", + get_decl_name(base), IDENTIFIER_POINTER (name)); + } + + /* atlast, do the real stuff */ + t = start_struct (code, name); + TYPE_CONTEXT(t) = base; + return t; +} + +/* concatenate the base's fields and the parsed fieldlist, + then simply call finish_struct - that's a simple way + to arrive at an inclusion that makes for a submorph struct + ... simple, purposeful, efficient, and very german ;-) -gud */ +tree +finish_struct_submorph (t, fieldlist, attributes) + tree t; + tree fieldlist; + tree attributes; +{ + register tree context; + register tree fields; + + if (!flag_cplusplus) + { + return finish_struct (t, fieldlist, attributes); + } + + if (t && TYPE_CONTEXT (t) && TYPE_FIELDS (TYPE_CONTEXT (t))) + { + fields = copy_list (TYPE_FIELDS (TYPE_CONTEXT (t))); + fields = chainon (fields, fieldlist); +#if 0 + /* merge the attributes of the baseclass into the current class ?? how ?? (this is wrong)*/ + attributes = merge_attributes (TYPE_ATTRIBUTES(TYPE_CONTEXT(t)), attributes); +#endif + } + else + { + warning ("submorph inclusion failed for `%s'", get_decl_name (t)); + fields = fieldlist; + } + + /* the relay to the older plain defining function can make for non-obvious messages */ + /* we should copy and adapt the finish_struct code to suit the needs + of the submorph-specialty, emitting more distinctive diagnostics + (esp: "duplicate member name" where one came from a submorph-base) -gud */ + + return finish_struct (t, fields, attributes); +} + /* Lay out the type T, and its element type, and so on. */ diff -u -r gcc-2.95.orig/gcc/c-parse.in gcc-2.95/gcc/c-parse.in --- gcc-2.95.orig/gcc/c-parse.in Fri Oct 1 14:34:10 1999 +++ gcc-2.95/gcc/c-parse.in Sat Oct 2 04:55:07 1999 @@ -1501,9 +1501,20 @@ } component_decl_list '}' maybe_attribute { $$ = finish_struct ($4, $5, chainon ($1, $7)); } + | struct_head identifier ':' identifier '{' + { $$ = start_struct_submorph (RECORD_TYPE, $2, $4)); + /* Start scope of tag before parsing components. */ + } + component_decl_list '}' maybe_attribute + { $$ = finish_struct_submorph ($6, $7, chainon ($1, $9)); } | struct_head '{' component_decl_list '}' maybe_attribute { $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE), $3, chainon ($1, $5)); + } + | struct_head ':' identifier '{' component_decl_list '}' maybe_attribute + { $$ = finish_struct_submorph ( + start_struct_submorph (RECORD_TYPE, NULL_TREE, $3), + $5, chainon ($1, $7)); } | struct_head identifier { $$ = xref_tag (RECORD_TYPE, $2); } diff -u -r gcc-2.95.orig/gcc/c-parse.y gcc-2.95/gcc/c-parse.y --- gcc-2.95.orig/gcc/c-parse.y Fri Oct 1 14:34:10 1999 +++ gcc-2.95/gcc/c-parse.y Sat Oct 2 04:55:07 1999 @@ -1326,9 +1326,20 @@ } component_decl_list '}' maybe_attribute { $$ = finish_struct ($4, $5, chainon ($1, $7)); } + | struct_head identifier ':' identifier '{' + { $$ = start_struct_submorph (RECORD_TYPE, $2, $4); + /* Start scope of tag before parsing components. */ + } + component_decl_list '}' maybe_attribute + { $$ = finish_struct_submorph ($6, $7, chainon ($1, $9)); } | struct_head '{' component_decl_list '}' maybe_attribute { $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE), $3, chainon ($1, $5)); + } + | struct_head ':' identifier '{' component_decl_list '}' maybe_attribute + { $$ = finish_struct_submorph ( + start_struct_submorph (RECORD_TYPE, NULL_TREE, $3), + $5, chainon ($1, $7)); } | struct_head identifier { $$ = xref_tag (RECORD_TYPE, $2); } diff -u -r gcc-2.95.orig/gcc/c-tree.h gcc-2.95/gcc/c-tree.h --- gcc-2.95.orig/gcc/c-tree.h Fri Oct 1 14:34:10 1999 +++ gcc-2.95/gcc/c-tree.h Sat Oct 2 04:55:07 1999 @@ -303,6 +303,7 @@ extern tree finish_enum PROTO((tree, tree, tree)); extern void finish_function PROTO((int)); extern tree finish_struct PROTO((tree, tree, tree)); +extern tree finish_struct_submorph PROTO((tree, tree, tree)); extern tree get_parm_info PROTO((int)); extern tree getdecls PROTO((void)); extern tree gettags PROTO((void)); @@ -347,8 +348,11 @@ extern tree start_decl PROTO((tree, tree, int, tree, tree)); extern tree start_struct PROTO((enum tree_code, tree)); +extern tree start_struct_submorph PROTO((enum tree_code, tree, tree)); extern void store_parm_decls PROTO((void)); extern tree xref_tag PROTO((enum tree_code, tree)); + +extern char* get_decl_name PROTO((tree decl)); /* in c-typeck.c */ extern tree require_complete_type PROTO((tree)); diff -u -r gcc-2.95.orig/gcc/c-typeck.c gcc-2.95/gcc/c-typeck.c --- gcc-2.95.orig/gcc/c-typeck.c Fri Oct 1 14:34:10 1999 +++ gcc-2.95/gcc/c-typeck.c Sat Oct 2 04:55:07 1999 @@ -4017,6 +4017,204 @@ NULL_TREE, NULL_TREE, 0); } + +/* two structures are inclusion-submorph iff + - all simple types of lhs are present in the rhs with the + a) same name + b) same offset + c) same size + d) the qualifiers of lhs's contained type is more or equal restrictive + than the the corresponding rhs contained type that fulfilled a)+b)+c) + - we don't care about record names as long as their simple type members + meet above's condition + - the lhs may be shorter than the rhs struct +*/ + +/* + returns: + return: lhs_tail, if 0 the lhs-tree has been matched, so it is an upmorph atleast + outarg: rhs_tail, if 0 the rhs-tree has been matched completly, + + ie. if rhs_tail-return _and_ lhs_tail-outarg are null + then the structures are isomorph. + if lhs_tail-return is null _and_ rhs_tail is non-null + then the lhs-structure is a upmorph of the rhs-structure + if lhs_tail-return is non-null _and_ rhs_tail is null + then the rhs-structure is *possibly* a upmorph of the lhs-structure + if both lhs_tail and rhs_tail are non-null + then the structure are non-upmorph to each other + ... so checking for if (!tail_submorph(lhs, rhs, &some)) is mostly the thing you want to do... +*/ + + /* debugging macro, left here for patch-distribution, use at your option */ +#define notice_lhs_rhs( what, lhs, rhs) \ +{ if (extra_warnings && warn_cast_qual) {\ + notice (what" \tlhs= '%s' <%s %s> rhs= '%s' <%s %s>\n", \ + get_decl_name (lhs), (lhs ? tree_code_name[(int) TREE_CODE(lhs)] : "0"), ((lhs && TREE_TYPE(lhs)) ? tree_code_name[(int) TREE_CODE(TREE_TYPE(lhs))] : "0"), \ + get_decl_name (rhs), (rhs ? tree_code_name[(int) TREE_CODE(rhs)] : "0"), ((rhs && TREE_TYPE(rhs)) ? tree_code_name[(int) TREE_CODE(TREE_TYPE(rhs))] : "0")); \ +} } + +tree +tail_submorph (lhs_, rhs_, tail) + tree lhs_; + tree rhs_; + tree* tail; +{ + register tree lhs = lhs_; + register tree rhs = rhs_; + if (!tail) { + warning ("* internal error: forgot to provide tail-out-arg at tail_submorph function"); + return lhs; + } + + /* check the currents */ + notice_lhs_rhs (" >>>>>> ", lhs, rhs); + + /* if currents are indirections, just go down the indirection + chain till we come to their actual type */ + while (TREE_CODE (lhs) == TREE_CODE (rhs) + && (TREE_CODE (lhs) == POINTER_TYPE + || TREE_CODE (lhs) == ARRAY_REF + || TREE_CODE (lhs) == INDIRECT_REF + || TREE_CODE (lhs) == CALL_EXPR ) + ) + { + // rhs = TREE_OPERAND (rhs, 0); + // lhs = TREE_OPERAND (lhs, 0); + rhs = TREE_TYPE (rhs); + lhs = TREE_TYPE (lhs); + } + + /* if currents happens to be a RECORD_TYPE, then they must be submorph + or we can already fail for the currents */ + if (TREE_CODE (lhs) == TREE_CODE (rhs) + && TREE_CODE (lhs) == RECORD_TYPE) + { + return (tail_submorph (TYPE_FIELDS (lhs), TYPE_FIELDS(rhs), tail)); + /* tail recursion */ + } + + /*if we are at some other field, check each field in turn*/ + while ( (lhs) && (rhs) + && (TREE_CODE(lhs) == FIELD_DECL || TREE_CODE(lhs) == TYPE_DECL) + && (TREE_CODE(rhs) == FIELD_DECL || TREE_CODE(rhs) == TYPE_DECL) + ) { + + notice_lhs_rhs (" check... ", lhs, rhs); + if (TREE_TYPE (lhs) == TREE_TYPE (rhs)) /* identical */ + { + if (TREE_CODE (lhs) == FIELD_DECL && TREE_CODE (rhs) == FIELD_DECL) + { + if (DECL_NAME (lhs) && DECL_NAME (rhs) + && DECL_NAME (lhs) != DECL_NAME (rhs)) + { + extern int warn_fieldnames_different; + if (warn_fieldnames_different || warn_cast_qual) + { + warning (" different names for fields `:%s:%s' vs. `:%s:%s'", + lhs_ != lhs ? get_decl_name (lhs_) : "", get_decl_name (lhs), + rhs_ != rhs ? get_decl_name (rhs_) : "", get_decl_name (rhs)); + } + /*no break*/ + } + if (DECL_FIELD_SIZE (lhs) && DECL_FIELD_SIZE (rhs) + && DECL_FIELD_SIZE (lhs) != DECL_FIELD_SIZE (rhs)) + { + warning (" different sizes for fields `:%s:%s' (%i) vs. `:%s:%s' (%i)", + lhs_ != lhs ? get_decl_name (lhs_) : "", get_decl_name (lhs), DECL_FIELD_SIZE(lhs), + rhs_ != rhs ? get_decl_name (rhs_) : "", get_decl_name (rhs), DECL_FIELD_SIZE(rhs)); + break; + } + if (DECL_FIELD_BITPOS (lhs) != DECL_FIELD_BITPOS (rhs) + && TREE_INT_CST_LOW(DECL_FIELD_BITPOS(lhs)) != TREE_INT_CST_LOW(DECL_FIELD_BITPOS(rhs))) + { + warning (" different offsets for fields `:%s:%s' (%i/8) vs. `:%s:%s' (%i/8)", + lhs_ != lhs ? get_decl_name (lhs_) : "", get_decl_name (lhs), TREE_INT_CST_LOW(DECL_FIELD_BITPOS(lhs)), + rhs_ != rhs ? get_decl_name (rhs_) : "", get_decl_name (rhs), TREE_INT_CST_LOW(DECL_FIELD_BITPOS(rhs))); + break; + } + } + + notice_lhs_rhs (" ...ok ", lhs, rhs); + lhs = TREE_CHAIN (lhs), rhs = TREE_CHAIN (rhs); /* next fields */ + continue; + } + + if (TREE_CODE (TREE_TYPE(lhs)) == TREE_CODE (TREE_TYPE(rhs)) + && (TREE_CODE (TREE_TYPE(lhs)) == POINTER_TYPE + || TREE_CODE (TREE_TYPE(lhs)) == ARRAY_REF + || TREE_CODE (TREE_TYPE(lhs)) == INDIRECT_REF + || TREE_CODE (TREE_TYPE(lhs)) == CALL_EXPR ) + ) { + notice_lhs_rhs (" -indirect- ", lhs, rhs); + if (!tail_submorph (TREE_TYPE(lhs), TREE_TYPE(rhs), tail)) + { + lhs = TREE_CHAIN (lhs), rhs = TREE_CHAIN (rhs); + continue; + }else{ + break; + } + } + + if (/*TREE_CODE (TREE_TYPE(lhs)) != RECORD_TYPE &&*/ TREE_CODE(TREE_TYPE(rhs)) == RECORD_TYPE) + { + notice_lhs_rhs (" -rhs-rec- ", lhs, rhs); + lhs = tail_submorph (lhs, TYPE_FIELDS(TREE_TYPE(rhs)), tail); + rhs = (*tail) ? (*tail) : TREE_CHAIN (rhs); + notice_lhs_rhs (" (rhs-rec) ", lhs, rhs); + continue; + } + if (/*TREE_CODE (TREE_TYPE(rhs)) != RECORD_TYPE &&*/ TREE_CODE(TREE_TYPE(lhs)) == RECORD_TYPE) + { + notice_lhs_rhs (" -lhs-rec- ", lhs, rhs); + { register tree x = tail_submorph (TYPE_FIELDS(TREE_TYPE(lhs)), rhs, tail); + lhs = (x) ? (x) : TREE_CHAIN (lhs); + } + rhs = *tail; + notice_lhs_rhs (" (lhs-rec) ", lhs, rhs); + continue; + } + + notice_lhs_rhs (" --none-- ", lhs, rhs); + break; + } /*foreach field*/ + + notice_lhs_rhs (" <<< ", lhs, rhs); + *tail = rhs; + return lhs; +} + +int +is_submorph (lhs, rhs) + tree lhs; + tree rhs; +{ + tree tail; + if (!warn_cast_qual) + { + return (!tail_submorph (lhs, rhs, &tail)); + } + else + { + if (!tail_submorph (lhs, rhs, &tail)) + { + if (!tail) { + warning ("isoMORPH ('%s' <> '%s')", get_decl_name(lhs), get_decl_name(rhs)); + }else{ + warning ("subMORPH ('%s' <>downcast>> '%s')", get_decl_name(lhs), get_decl_name(rhs)); + }else{ + warning ("NONmorph ('%s' >>different<< '%s')", get_decl_name(lhs), get_decl_name(rhs)); + } + return 0; + } + } +} + /* Convert value RHS to type TYPE as preparation for an assignment to an lvalue of type TYPE. The real work of conversion is done by `convert'. @@ -4232,8 +4430,14 @@ } } else - warn_for_assignment ("%s from incompatible pointer type", - errtype, funname, parmnum); + { + /* targets don't need to be actually the same, just applicable - + here we look through the list of primary members on the rhs */ + extern int flag_cplusplus; + if (pedantic || !flag_cplusplus || !is_submorph (ttl, ttr)) + warn_for_assignment ("%s from incompatible pointer type", + errtype, funname, parmnum); + } return convert (type, rhs); } else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)