From f3ba5c6a46451d8ce4a1a6283683acf071d855ff Mon Sep 17 00:00:00 2001 From: mrs Date: Fri, 5 Aug 1994 20:25:20 +0000 Subject: [PATCH] 45th Cygnus<->FSF merge git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@7862 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 148 +++++++++++++++++++++++++++++++++++++++++++--- gcc/cp/Makefile.in | 2 +- gcc/cp/call.c | 18 ++---- gcc/cp/class.c | 111 ++++++++++++++++++++++++++++------- gcc/cp/cp-tree.h | 1 - gcc/cp/cvt.c | 23 ++++---- gcc/cp/decl.c | 47 ++++++++------- gcc/cp/decl2.c | 13 ++++- gcc/cp/error.c | 13 ++++- gcc/cp/init.c | 2 +- gcc/cp/lex.c | 2 +- gcc/cp/method.c | 4 +- gcc/cp/parse.y | 55 +++++++++-------- gcc/cp/pt.c | 169 ++++++++++++++++++++++++++++++++++------------------- gcc/cp/search.c | 20 +++++-- gcc/cp/tree.c | 157 +++++++++++++++++++------------------------------ gcc/cp/typeck.c | 30 ++++++++-- gcc/cp/typeck2.c | 2 +- 18 files changed, 541 insertions(+), 276 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8a5d7fd..7ee24e6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,18 +1,148 @@ +Fri Aug 5 01:12:20 1994 Mike Stump (mrs@cygnus.com) + + * class.c (get_class_offset_1, get_class_offset): New routine to + find the offset of the class where a virtual function is defined, + from the complete type. + * class.c (modify_one_vtable, fixup_vtable_deltas): Use + get_class_offset instead of virtual_offset as get_class_offset will + always provide the right answer. + * tree.c (virtual_offset): Remove. It only ever worked some of the + time. + +Tue Aug 2 12:44:21 1994 Jason Merrill (jason@deneb.cygnus.com) + + * call.c (build_method_call): Put back unary_complex_lvalue call + that I thought was redundant. + + * typeck.c (c_expand_return): Fix a case I missed before. + +Sun Jul 31 17:54:02 1994 Jason Merrill (jason@deneb.cygnus.com) + + * pt.c (unify): Strip cv-quals from template type arguments (when + 'const T*' is matched to 'const char*', that does not mean that T is + 'const char'). + +Fri Jul 29 01:03:06 1994 Jason Merrill (jason@deneb.cygnus.com) + + * pt.c (do_type_instantiation): Instantiate nested TAGS, not + typedefs. Third time's the charm? + + * parse.y (template_parm): Support default template parms. + * pt.c (process_template_parm): Ditto. + (end_template_parm_list): Ditto. + (coerce_template_parms): Ditto. + (mangle_class_name_for_template): Ditto. + (push_template_decls): Ditto. + (unify): Ditto. + * method.c (build_overload_identifier): Ditto. + * error.c (dump_decl): Ditto. + +Wed Jul 27 17:47:00 1994 Jason Merrill (jason@deneb.cygnus.com) + + * pt.c (do_type_instantiation): Only instantiate nested *classes*. + +Tue Jul 26 13:22:40 1994 Jason Merrill (jason@deneb.cygnus.com) + + * search.c (note_debug_info_needed): Also emit debugging information + for the types of fields. + +Mon Jul 25 00:34:44 1994 Jason Merrill (jason@deneb.cygnus.com) + + * pt.c (lookup_template_class): Pass 'template' to + coerce_template_parms instead of 'in_decl', since it's a more + meaningful context. + + * typeck.c (c_expand_return): Make sure any cleanups for the return + expression get run. + (build_c_cast): Use CONVERT_EXPR for conversion to void. + + * pt.c (do_type_instantiation): Also instantiate nested types. + + * typeck.c (convert_for_assignment): Don't die when comparing + pointers with different levels of indirection. + + * decl.c (grokdeclarator): The sub-call to grokdeclarator for + class-local typedefs sets DECL_ARGUMENTS, so we need to clear it + out. + + * decl2.c (finish_anon_union): Don't die if the union has no + members. + + * decl.c (grokdeclarator): Undo changes to declspecs when we're done + so that 'typedef int foo, bar;' will work. + + * decl2.c (finish_file): Don't call expand_aggr_init for + non-aggregates. + +Mon Jul 25 00:03:10 1994 Teemu Torma (tot@trema.fi) + + * decl.c (finish_function): We can't inline constructors and + destructors under some conditions with -fpic, but don't unset + DECL_INLINE. + +Mon Jul 25 00:03:10 1994 Jason Merrill (jason@deneb.cygnus.com) + + * typeck.c (build_object_ref): Make sure 'datum' is a valid object. + +Sun Jul 24 14:19:31 1994 Jason Merrill (jason@deneb.cygnus.com) + + * class.c (finish_struct): Don't set DECL_FIELD_BITPOS on + non-fields. + (finish_struct_methods): Use copy_assignment_arg_p. + + * cvt.c (cp_convert): If expr is an OFFSET_REF, resolve it instead + of giving an error. + + * typeck.c (build_binary_op_nodefault): Don't set result_type if we + don't know how to compare the operands. + + * decl.c (grokdeclarator): Avoid seg fault when someone uses '__op' + as a declarator-id in their program. Like the Linux headers do. + Arrgh. + + * tree.c (lvalue_p): Treat calls to functions returning objects by + value as lvalues again. + + * typeck.c (build_component_addr): Use convert_force to convert the + pointer in case the component type is also a private base class. + + * search.c (get_matching_virtual): Fix bogus warning of overloaded + virtual. + + * pt.c (overload_template_name): Set DECL_ARTIFICIAL on the created + TYPE_DECL to fix bogus shadowing warnings. + +Fri Jul 22 01:15:32 1994 Jason Merrill (jason@deneb.cygnus.com) + + * init.c (expand_aggr_init_1): const and volatile mismatches do not + prevent a TARGET_EXPR from initializing an object directly. + +Tue Jul 19 17:55:37 1994 Jason Merrill (jason@deneb.cygnus.com) + + * cvt.c (build_up_reference): Allow building up references to + `this', don't warn about making references to artificial variables + (like `this'). + + * tree.c (lvalue_p): `this' is not an lvalue. + + * call.c (build_method_call): Accept using a typedef name (or + template type parameter) for explicit destructor calls. + Wed Jul 13 03:57:54 1994 Jason Merrill (jason@deneb.cygnus.com) - * method.c (hack_identifier): Put back old code so lists of - non-functions will be handled properly. + * method.c (hack_identifier): Put back old code so lists of + non-functions will be handled properly. - * cp-tree.h (TYPE_NEEDS_CONSTRUCTING): #if 0 out; this macro is now - defined in the language-independent tree.h. + * cp-tree.h (TYPE_NEEDS_CONSTRUCTING): #if 0 out; this macro is now + defined in the language-independent tree.h. - * tree.c (count_functions): Avoid bogus warning when compiling this - function. + * tree.c (count_functions): Avoid bogus warning when compiling this + function. Mon Jul 11 18:37:20 1994 Jason Merrill (jason@deneb.cygnus.com) - * decl.c (grok_reference_init): Always save the initializer of a - reference. + * decl.c (grok_reference_init): Always save the initializer of a + reference. Fri Jul 8 17:41:46 1994 Mike Stump (mrs@cygnus.com) @@ -36,7 +166,7 @@ Fri Jul 8 02:27:41 1994 Jason Merrill (jason@deneb.cygnus.com) * decl.c (push_overloaded_decl): Don't create overloads of one when shadowing a class type. - * typeck.c (build_x_function_call): Complain about overloads of one + * typeck.c (build_x_function_call): Complain about overloads of one. * decl.c (grokdeclarator): Don't try to treat a char* as a tree. (grokdeclarator): Fix setting of TREE_STATIC. diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in index 231d1a3..fa0bd49 100644 --- a/gcc/cp/Makefile.in +++ b/gcc/cp/Makefile.in @@ -193,7 +193,7 @@ parse.o : $(srcdir)/parse.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h `echo $(srcdir)/parse.c | sed 's,^\./,,'` $(srcdir)/parse.c $(srcdir)/parse.h : $(srcdir)/parse.y - @echo expect 1 shift/reduce confict and 33 reduce/reduce conflicts. + @echo expect 1 shift/reduce confict and 34 reduce/reduce conflicts. cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 3392a7a..254fd34 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -1604,21 +1604,15 @@ build_method_call (instance, name, parms, basetype_path, flags) if (parms) error ("destructors take no parameters"); basetype = TREE_TYPE (instance); - if (IS_AGGR_TYPE (basetype)) + if (! ((IS_AGGR_TYPE (basetype) + && name == constructor_name (basetype)) + || basetype == get_type_value (name))) { - if (name == constructor_name (basetype)) - goto huzzah; + cp_error ("destructor name `~%D' does not match type `%T' of expression", + name, basetype); + return void_zero_node; } - else - { - if (basetype == get_type_value (name)) - goto huzzah; - } - cp_error ("destructor name `~%D' does not match type `%T' of expression", - name, basetype); - return void_zero_node; - huzzah: if (! TYPE_HAS_DESTRUCTOR (basetype)) return void_zero_node; instance = default_conversion (instance); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index e715c89..6c767bb 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1830,8 +1830,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method) { tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields)); - if (TREE_CODE (parmtype) == REFERENCE_TYPE - && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == t) + if (copy_assignment_arg_p (parmtype, DECL_VIRTUAL_P (fn_fields))) { if (TREE_PROTECTED (fn_fields)) TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 1; @@ -2151,6 +2150,86 @@ overrides (fndecl, base_fndecl) return 0; } +static tree +get_class_offset_1 (parent, binfo, context, t, fndecl) + tree parent, binfo, context, t, fndecl; +{ + tree binfos = BINFO_BASETYPES (binfo); + int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + tree rval = NULL_TREE; + + if (binfo == parent) + return error_mark_node; + + for (i = 0; i < n_baselinks; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + tree nrval; + + if (TREE_VIA_VIRTUAL (base_binfo)) + base_binfo = binfo_member (BINFO_TYPE (base_binfo), + CLASSTYPE_VBASECLASSES (t)); + nrval = get_class_offset_1 (parent, base_binfo, context, t, fndecl); + /* See if we have a new value */ + if (nrval && (nrval != error_mark_node || rval==0)) + { + /* Only compare if we have two offsets */ + if (rval && rval != error_mark_node + && ! tree_int_cst_equal (nrval, rval)) + { + /* Only give error if the two offsets are different */ + error ("every virtual function must have a unique final overrider"); + cp_error (" found two (or more) `%T' class subobjects in `%T'", context, t); + cp_error (" with virtual `%D' from virtual base class", fndecl); + return rval; + } + rval = nrval; + } + + if (rval && BINFO_TYPE (binfo) == context) + { + my_friendly_assert (rval == error_mark_node + || tree_int_cst_equal (rval, BINFO_OFFSET (binfo)), 999); + rval = BINFO_OFFSET (binfo); + } + } + return rval; +} + +/* Get the offset to the CONTEXT subobject that is related to the + given BINFO. */ +static tree +get_class_offset (context, t, binfo, fndecl) + tree context, t, binfo, fndecl; +{ + tree first_binfo = binfo; + tree offset; + int i; + + if (context == t) + return integer_zero_node; + + if (BINFO_TYPE (binfo) == context) + return BINFO_OFFSET (binfo); + + /* Check less derived binfos first. */ + while (BINFO_BASETYPES (binfo) + && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1) + { + tree binfos = BINFO_BASETYPES (binfo); + binfo = TREE_VEC_ELT (binfos, i); + if (BINFO_TYPE (binfo) == context) + return BINFO_OFFSET (binfo); + } + + /* Ok, not found in the less derived binfos, now check the more + derived binfos. */ + offset = get_class_offset_1 (first_binfo, TYPE_BINFO (t), context, t, fndecl); + if (offset==0 || TREE_CODE (offset) != INTEGER_CST) + my_friendly_abort (999); /* we have to find it. */ + return offset; +} + static void modify_one_vtable (binfo, t, fndecl, pfn) tree binfo, t, fndecl, pfn; @@ -2174,16 +2253,7 @@ modify_one_vtable (binfo, t, fndecl, pfn) tree vfield = CLASSTYPE_VFIELD (t); tree this_offset; - offset = integer_zero_node; - if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t)) - { - offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset); - if (offset == NULL_TREE) - { - tree binfo = get_binfo (context, t, 0); - offset = BINFO_OFFSET (binfo); - } - } + offset = get_class_offset (context, t, binfo, fndecl); /* Find the right offset for the this pointer based on the base class we just found. We have to take into @@ -2288,16 +2358,7 @@ fixup_vtable_deltas (binfo, t) tree vfield = CLASSTYPE_VFIELD (t); tree this_offset; - offset = integer_zero_node; - if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t)) - { - offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset); - if (offset == NULL_TREE) - { - tree binfo = get_binfo (context, t, 0); - offset = BINFO_OFFSET (binfo); - } - } + offset = get_class_offset (context, t, binfo, fndecl); /* Find the right offset for the this pointer based on the base class we just found. We have to take into @@ -3498,6 +3559,9 @@ finish_struct (t, list_of_fieldlists, warn_anon) tree uelt = TYPE_FIELDS (TREE_TYPE (field)); for (; uelt; uelt = TREE_CHAIN (uelt)) { + if (TREE_CODE (uelt) != FIELD_DECL) + continue; + DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field); DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field); } @@ -3552,6 +3616,9 @@ finish_struct (t, list_of_fieldlists, warn_anon) tree uelt = TYPE_FIELDS (TREE_TYPE (field)); for (; uelt; uelt = TREE_CHAIN (uelt)) { + if (TREE_CODE (uelt) != FIELD_DECL) + continue; + DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field); DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field); } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 80fd832..b6db695 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2254,7 +2254,6 @@ extern tree copy_binfo PROTO((tree)); extern tree binfo_value PROTO((tree, tree)); extern tree reverse_path PROTO((tree)); extern tree virtual_member PROTO((tree, tree)); -extern tree virtual_offset PROTO((tree, tree, tree)); extern void debug_binfo PROTO((tree)); extern int decl_list_length PROTO((tree)); extern int count_functions PROTO((tree)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index cb8d968..04f9bd3 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -425,10 +425,11 @@ build_up_reference (type, arg, flags, checkconst) break; case PARM_DECL: +#if 0 if (targ == current_class_decl) { error ("address of `this' not available"); -#if 0 +/* #if 0 */ /* This code makes the following core dump the compiler on a sun4, if the code below is used. @@ -465,16 +466,18 @@ build_up_reference (type, arg, flags, checkconst) TREE_ADDRESSABLE (targ) = 1; /* so compiler doesn't die later */ put_var_into_stack (targ); break; -#else +/* #else */ return error_mark_node; -#endif +/* #endif */ } +#endif /* Fall through. */ case VAR_DECL: case CONST_DECL: - if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ)) - warning ("address needed to build reference for `%s', which is declared `register'", - IDENTIFIER_POINTER (DECL_NAME (targ))); + if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ) + && !DECL_ARTIFICIAL (targ)) + cp_warning ("address needed to build reference for `%D', which is declared `register'", + targ); else if (staticp (targ)) literal_flag = 1; @@ -1206,6 +1209,9 @@ cp_convert (type, expr, convtype, flags) else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE) e = convert_from_reference (e); + if (TREE_CODE (e) == OFFSET_REF) + e = resolve_offset_ref (e); + if (TREE_READONLY_DECL_P (e)) e = decl_constant_value (e); @@ -1223,10 +1229,7 @@ cp_convert (type, expr, convtype, flags) if (flag_pedantic_errors) return error_mark_node; } - if (form == OFFSET_TYPE) - cp_error_at ("pointer-to-member expression object not composed with type `%D' object", - TYPE_NAME (TYPE_OFFSET_BASETYPE (intype))); - else if (IS_AGGR_TYPE (intype)) + if (IS_AGGR_TYPE (intype)) { tree rval; rval = build_type_conversion (CONVERT_EXPR, type, e, 1); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 0690340..11ea6a2 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7091,7 +7091,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) dname = decl; decl = NULL_TREE; - if (IDENTIFIER_OPNAME_P (dname)) + if (! IDENTIFIER_OPNAME_P (dname) + /* Linux headers use '__op'. Arrgh. */ + || IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname)) + name = IDENTIFIER_POINTER (dname); + else { if (IDENTIFIER_TYPENAME_P (dname)) { @@ -7102,8 +7106,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) } name = operator_name_string (dname); } - else - name = IDENTIFIER_POINTER (dname); break; case RECORD_TYPE: @@ -7688,17 +7690,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) break; } - if (scanner == IDENTIFIER_AS_LIST (ridpointers [(int) RID_TYPEDEF])) - { - if (previous_declspec) - TREE_CHAIN (previous_declspec) - = IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]); - else - declspecs - = IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]); - } + if (previous_declspec) + TREE_CHAIN (previous_declspec) = TREE_CHAIN (scanner); else - TREE_VALUE (scanner) = ridpointers[(int) RID_STATIC]; + declspecs = TREE_CHAIN (scanner); + + declspecs = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], + declspecs); /* In the recursive call to grokdeclarator we need to know whether we are working on a signature-local typedef. */ @@ -7707,6 +7705,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) loc_typedecl = grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE); + + if (previous_declspec) + TREE_CHAIN (previous_declspec) = scanner; if (loc_typedecl != error_mark_node) { @@ -7714,6 +7715,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) register int *pi; TREE_SET_CODE (loc_typedecl, TYPE_DECL); + /* This is the same field as DECL_ARGUMENTS, which is set for + function typedefs by the above grokdeclarator. */ + DECL_NESTED_TYPENAME (loc_typedecl) = 0; pi = (int *) permalloc (sizeof (struct lang_decl_flags)); while (i > 0) @@ -11529,20 +11533,19 @@ finish_function (lineno, call_poplevel) /* So we can tell if jump_optimize sets it to 1. */ can_reach_end = 0; - /* ??? Compensate for Sun brain damage in dealing with data segments - of PIC code. */ - if (flag_pic - && (DECL_CONSTRUCTOR_P (fndecl) - || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) - && CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype))) - DECL_INLINE (fndecl) = 0; - if (DECL_EXTERNAL (fndecl) /* This function is just along for the ride. If we can make it inline, that's great. Otherwise, just punt it. */ && (DECL_INLINE (fndecl) == 0 || flag_no_inline - || function_cannot_inline_p (fndecl))) + || function_cannot_inline_p (fndecl) + /* ??? Compensate for Sun brain damage in dealing with + data segments of PIC code. */ + || (flag_pic + && (DECL_CONSTRUCTOR_P (fndecl) + || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) + && CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype))))) + { extern int rtl_dump_and_exit; int old_rtl_dump_and_exit = rtl_dump_and_exit; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 2b9f8a7..6579fe7 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -2100,8 +2100,16 @@ finish_anon_union (anon_union_decl) } if (static_p) { - make_decl_rtl (main_decl, 0, global_bindings_p ()); - DECL_RTL (anon_union_decl) = DECL_RTL (main_decl); + if (main_decl) + { + make_decl_rtl (main_decl, 0, global_bindings_p ()); + DECL_RTL (anon_union_decl) = DECL_RTL (main_decl); + } + else + { + warning ("anonymous union with no members"); + return; + } } /* The following call assumes that there are never any cleanups @@ -2712,7 +2720,6 @@ finish_file () } } if (IS_AGGR_TYPE (TREE_TYPE (decl)) - || init == 0 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) expand_aggr_init (decl, init, 0); else if (TREE_CODE (init) == TREE_VEC) diff --git a/gcc/cp/error.c b/gcc/cp/error.c index f431f6a..c427243 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -671,13 +671,22 @@ dump_decl (t, v) for (i = 0; i < len; i++) { tree arg = TREE_VEC_ELT (args, i); - if (TREE_CODE (arg) == IDENTIFIER_NODE) + tree defval = TREE_PURPOSE (arg); + arg = TREE_VALUE (arg); + if (TREE_CODE (arg) == TYPE_DECL) { OB_PUTS ("class "); - OB_PUTID (arg); + OB_PUTID (DECL_NAME (arg)); } else dump_decl (arg, 1); + + if (defval) + { + OB_PUTS (" = "); + dump_decl (defval, 1); + } + OB_PUTC2 (',', ' '); } OB_UNPUT (2); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 5e5d580..4aec96a 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1392,7 +1392,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags) separately from the object being initialized. */ if (TREE_CODE (init) == TARGET_EXPR) { - if (init_type == type) + if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type)) { if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == RESULT_DECL) diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 5edf659..2d41cc6 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -2875,7 +2875,7 @@ linenum: if (c_header_level && --c_header_level == 0) { if (entering_c_header) - warning ("Badly nested C headers from preprocessor"); + warning ("badly nested C headers from preprocessor"); --pending_lang_change; } if (flag_cadillac) diff --git a/gcc/cp/method.c b/gcc/cp/method.c index f64a16a..853ada1 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -463,9 +463,9 @@ build_overload_identifier (name) icat (nparms); for (i = 0; i < nparms; i++) { - tree parm = TREE_VEC_ELT (parmlist, i); + tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i)); tree arg = TREE_VEC_ELT (arglist, i); - if (TREE_CODE (parm) == IDENTIFIER_NODE) + if (TREE_CODE (parm) == TYPE_DECL) { /* This parameter is a type. */ OB_PUTC ('Z'); diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index d30e511..9251a34 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -221,7 +221,7 @@ empty_parms () %type type_id absdcl type_quals %type direct_abstract_declarator conversion_declarator %type new_type_id new_declarator direct_new_declarator -%type xexpr parmlist parms parm bad_parm +%type xexpr parmlist parms parm bad_parm full_parm %type identifiers_or_typenames %type fcast_or_absdcl regcast_or_absdcl sub_cast_expr %type expr_or_declarator complex_notype_declarator @@ -250,6 +250,7 @@ empty_parms () %type nonmomentary_expr %type forhead.2 initdcl0 notype_initdcl0 member_init_list %type template_header template_parm_list template_parm +%type template_type_parm %type template_type template_arg_list template_arg %type template_instantiation template_type_name tmpl.2 %type template_instantiate_once template_instantiate_some @@ -373,6 +374,20 @@ template_parm_list: { $$ = process_template_parm ($1, $3); } ; +template_type_parm: + aggr + { + $$ = build_tree_list ($1, NULL_TREE); + ttpa: + if (TREE_PURPOSE ($$) == signature_type_node) + sorry ("signature as template type parameter"); + else if (TREE_PURPOSE ($$) != class_type_node) + pedwarn ("template type parameters must use the keyword `class'"); + } + | aggr identifier + { $$ = build_tree_list ($1, $2); goto ttpa; } + ; + template_parm: /* The following rules introduce a new reduce/reduce conflict on the ',' and '>' input tokens: they are valid @@ -381,24 +396,11 @@ template_parm: By putting them before the `parm' rule, we get their match before considering them nameless parameter declarations. */ - aggr identifier - { - if ($1 == signature_type_node) - sorry ("signature as template type parameter"); - else if ($1 != class_type_node) - error ("template type parameter must use keyword `class'"); - $$ = build_tree_list ($2, NULL_TREE); - } - | aggr identifier_defn ':' base_class.1 - { - if ($1 == signature_type_node) - sorry ("signature as template type parameter"); - else if ($1 != class_type_node) - error ("template type parameter must use keyword `class'"); - warning ("restricted template type parameters not yet implemented"); - $$ = build_tree_list ($2, $4); - } - | parm + template_type_parm + { $$ = build_tree_list (NULL_TREE, $$); } + | template_type_parm '=' typespec + { $$ = build_tree_list ($3, $$); } + | full_parm ; overloaddef: @@ -782,6 +784,8 @@ template_type: template_type_name: PTYPENAME '<' template_arg_list '>' { $$ = lookup_template_class ($$, $3, NULL_TREE); } + | PTYPENAME '<' '>' + { $$ = lookup_template_class ($$, NULL_TREE, NULL_TREE); } | TYPENAME '<' template_arg_list '>' { $$ = lookup_template_class ($$, $3, NULL_TREE); } ; @@ -3550,10 +3554,8 @@ parms: { $$ = build_tree_list (NULL_TREE, $$); } | parm '=' init { $$ = build_tree_list ($3, $$); } - | parms_comma parm - { $$ = chainon ($$, build_tree_list (NULL_TREE, $2)); } - | parms_comma parm '=' init - { $$ = chainon ($$, build_tree_list ($4, $2)); } + | parms_comma full_parm + { $$ = chainon ($$, $2); } | parms_comma bad_parm { $$ = chainon ($$, build_tree_list (NULL_TREE, $2)); } | parms_comma bad_parm '=' init @@ -3599,6 +3601,13 @@ named_parm: { $$ = build_tree_list ($$, $2); } ; +full_parm: + parm + { $$ = build_tree_list (NULL_TREE, $$); } + | parm '=' init + { $$ = build_tree_list ($3, $$); } + ; + parm: named_parm | type_id diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c808cf4..e17354a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -81,18 +81,19 @@ process_template_parm (list, next) { tree parm; tree decl = 0; + tree defval; int is_type; parm = next; my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259); - is_type = TREE_CODE (TREE_PURPOSE (parm)) == IDENTIFIER_NODE; + defval = TREE_PURPOSE (parm); + parm = TREE_VALUE (parm); + is_type = TREE_PURPOSE (parm) == class_type_node; if (!is_type) { tree tinfo = 0; - parm = TREE_PURPOSE (parm); - my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 260); - parm = TREE_VALUE (parm); + my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260); /* is a const-param */ - parm = grokdeclarator (TREE_VALUE (next), TREE_PURPOSE (next), + parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm), PARM, 0, NULL_TREE); /* A template parameter is not modifiable. */ TREE_READONLY (parm) = 1; @@ -117,11 +118,19 @@ process_template_parm (list, next) else { tree t = make_node (TEMPLATE_TYPE_PARM); - decl = build_decl (TYPE_DECL, TREE_PURPOSE (parm), t); - TYPE_NAME (t) = decl; - TREE_VALUE (parm) = t; + decl = build_decl (TYPE_DECL, TREE_VALUE (parm), t); + TYPE_MAIN_DECL (t) = decl; + parm = decl; + if (defval) + { + if (IDENTIFIER_HAS_TYPE_VALUE (defval)) + defval = IDENTIFIER_TYPE_VALUE (defval); + else + defval = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (defval)); + } } pushdecl (decl); + parm = build_tree_list (defval, parm); return chainon (list, parm); } @@ -135,6 +144,7 @@ end_template_parm_list (parms) tree parms; { int nparms = 0; + int saw_default = 0; tree saved_parmlist; tree parm; for (parm = parms; parm; parm = TREE_CHAIN (parm)) @@ -143,13 +153,19 @@ end_template_parm_list (parms) for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++) { - tree p = parm; - if (TREE_CODE (p) == TREE_LIST) + tree p = TREE_VALUE (parm); + if (TREE_PURPOSE (parm)) + saw_default = 1; + else if (saw_default) + { + error ("if a default argument is given for one template parameter"); + error ("default arguments must be given for all subsequent"); + error ("parameters as well"); + } + + if (TREE_CODE (p) == TYPE_DECL) { - tree t = TREE_VALUE (p); - TREE_VALUE (p) = NULL_TREE; - p = TREE_PURPOSE (p); - my_friendly_assert (TREE_CODE (p) == IDENTIFIER_NODE, 261); + tree t = TREE_TYPE (p); TEMPLATE_TYPE_SET_INFO (t, saved_parmlist, nparms); } else @@ -158,7 +174,7 @@ end_template_parm_list (parms) DECL_INITIAL (p) = NULL_TREE; TEMPLATE_CONST_SET_INFO (tinfo, saved_parmlist, nparms); } - TREE_VEC_ELT (saved_parmlist, nparms) = p; + TREE_VEC_ELT (saved_parmlist, nparms) = parm; } set_current_level_tags_transparency (1); processing_template_decl++; @@ -354,47 +370,63 @@ coerce_template_parms (parms, arglist, in_decl) tree parms, arglist; tree in_decl; { - int nparms, i, lost = 0; + int nparms, nargs, i, lost = 0; tree vec; - if (TREE_CODE (arglist) == TREE_VEC) - nparms = TREE_VEC_LENGTH (arglist); + if (arglist == NULL_TREE) + nargs = 0; + else if (TREE_CODE (arglist) == TREE_VEC) + nargs = TREE_VEC_LENGTH (arglist); else - nparms = list_length (arglist); - if (nparms != TREE_VEC_LENGTH (parms)) + nargs = list_length (arglist); + + nparms = TREE_VEC_LENGTH (parms); + + if (nargs > nparms + || (nargs < nparms + && TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)) == NULL_TREE)) { error ("incorrect number of parameters (%d, should be %d)", - nparms, TREE_VEC_LENGTH (parms)); + nargs, nparms); if (in_decl) cp_error_at ("in template expansion for decl `%D'", in_decl); return error_mark_node; } - if (TREE_CODE (arglist) == TREE_VEC) + if (arglist && TREE_CODE (arglist) == TREE_VEC) vec = copy_node (arglist); else { vec = make_tree_vec (nparms); for (i = 0; i < nparms; i++) { - tree arg = arglist; - arglist = TREE_CHAIN (arglist); - if (arg == error_mark_node) - lost++; + tree arg; + + if (arglist) + { + arg = arglist; + arglist = TREE_CHAIN (arglist); + + if (arg == error_mark_node) + lost++; + else + arg = TREE_VALUE (arg); + } else - arg = TREE_VALUE (arg); + arg = TREE_PURPOSE (TREE_VEC_ELT (parms, i)); + TREE_VEC_ELT (vec, i) = arg; } } for (i = 0; i < nparms; i++) { tree arg = TREE_VEC_ELT (vec, i); - tree parm = TREE_VEC_ELT (parms, i); + tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); tree val = 0; int is_type, requires_type; is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't'; - requires_type = TREE_CODE (parm) == IDENTIFIER_NODE; + requires_type = TREE_CODE (parm) == TYPE_DECL; if (is_type != requires_type) { if (in_decl) @@ -415,7 +447,7 @@ coerce_template_parms (parms, arglist, in_decl) { grok_template_type (vec, &TREE_TYPE (parm)); val = digest_init (TREE_TYPE (parm), arg, (tree *) 0); - + if (val == error_mark_node) ; @@ -489,12 +521,13 @@ mangle_class_name_for_template (name, parms, arglist) my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268); for (i = 0; i < nparms; i++) { - tree parm = TREE_VEC_ELT (parms, i), arg = TREE_VEC_ELT (arglist, i); + tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); + tree arg = TREE_VEC_ELT (arglist, i); if (i) ccat (','); - if (TREE_CODE (parm) == IDENTIFIER_NODE) + if (TREE_CODE (parm) == TYPE_DECL) { cat (type_as_string (arg, 0)); continue; @@ -573,7 +606,7 @@ lookup_template_class (d1, arglist, in_decl) } parmlist = DECL_TEMPLATE_PARMS (template); - arglist = coerce_template_parms (parmlist, arglist, in_decl); + arglist = coerce_template_parms (parmlist, arglist, template); if (arglist == error_mark_node) return error_mark_node; if (uses_template_parms (arglist)) @@ -619,11 +652,11 @@ push_template_decls (parmlist, arglist, class_level) for (i = 0; i < nparms; i++) { int requires_type, is_type; - tree parm = TREE_VEC_ELT (parmlist, i); + tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i)); tree arg = TREE_VEC_ELT (arglist, i); tree decl = 0; - requires_type = TREE_CODE (parm) == IDENTIFIER_NODE; + requires_type = TREE_CODE (parm) == TYPE_DECL; is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't'; if (is_type) { @@ -635,7 +668,7 @@ push_template_decls (parmlist, arglist, class_level) } decl = arg; my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't', 273); - decl = build_decl (TYPE_DECL, parm, decl); + decl = build_decl (TYPE_DECL, DECL_NAME (parm), decl); } else { @@ -878,9 +911,8 @@ instantiate_member_templates (classname) case 1: /* Failure. */ failure: - cp_error ("type unification error instantiating %T::%D", - classname, tdecl); - cp_error_at ("for template declaration `%D'", tdecl); + cp_error_at ("type unification error instantiating `%D'", tdecl); + cp_error ("while instantiating members of `%T'", classname); continue /* loop of members */; default: @@ -1781,6 +1813,7 @@ overload_template_name (id, classlevel) || TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286); decl = build_decl (TYPE_DECL, template, t); + SET_DECL_ARTIFICIAL (decl); #if 0 /* fix this later */ /* We don't want to call here if the work has already been done. */ @@ -2035,22 +2068,20 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) return 1; } idx = TEMPLATE_TYPE_IDX (parm); + /* Template type parameters cannot contain cv-quals; i.e. + template void f (T& a, T& b) will not generate + void f (const int& a, const int& b). */ + if (TYPE_READONLY (arg) > TYPE_READONLY (parm) + || TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm)) + return 1; + arg = TYPE_MAIN_VARIANT (arg); /* Simple cases: Value already set, does match or doesn't. */ if (targs[idx] == arg) return 0; else if (targs[idx]) - { - if (TYPE_MAIN_VARIANT (targs[idx]) == TYPE_MAIN_VARIANT (arg)) - /* allow different parms to have different cv-qualifiers */; - else - return 1; - } - /* Check for mixed types and values. */ - if (TREE_CODE (TREE_VEC_ELT (tparms, idx)) != IDENTIFIER_NODE) return 1; - /* Allow trivial conversions. */ - if (TYPE_READONLY (parm) < TYPE_READONLY (arg) - || TYPE_VOLATILE (parm) < TYPE_VOLATILE (arg)) + /* Check for mixed types and values. */ + if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TYPE_DECL) return 1; targs[idx] = arg; return 0; @@ -2399,12 +2430,11 @@ do_type_instantiation (name, storage) tree t = TREE_TYPE (name); int extern_p; + /* With -fexternal-templates, explicit instantiations are treated the same + as implicit ones. */ if (flag_external_templates) return; - if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && ! CLASSTYPE_INTERFACE_ONLY (t)) - return; - if (TYPE_SIZE (t) == NULL_TREE) { cp_error ("explicit instantiation of `%#T' before definition of template", @@ -2423,6 +2453,14 @@ do_type_instantiation (name, storage) extern_p = 0; } + /* We've already instantiated this. */ + if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && ! CLASSTYPE_INTERFACE_ONLY (t)) + { + if (! extern_p) + cp_pedwarn ("multiple explicit instantiation of `%#T'", t); + return; + } + SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t); CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p; SET_CLASSTYPE_INTERFACE_KNOWN (t); @@ -2436,17 +2474,26 @@ do_type_instantiation (name, storage) /* this should really be done by instantiate_member_templates */ { - tree method = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0); - for (; method; method = TREE_CHAIN (method)) + tree tmp = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0); + for (; tmp; tmp = TREE_CHAIN (tmp)) { - SET_DECL_EXPLICIT_INSTANTIATION (method); - TREE_PUBLIC (method) = 1; - DECL_EXTERNAL (method) - = (extern_p || (DECL_INLINE (method) && ! flag_implement_inlines)); + SET_DECL_EXPLICIT_INSTANTIATION (tmp); + TREE_PUBLIC (tmp) = 1; + DECL_EXTERNAL (tmp) + = (extern_p || (DECL_INLINE (tmp) && ! flag_implement_inlines)); } - } - /* and data member templates, too */ +#if 0 + for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp)) + { + if (TREE_CODE (tmp) == VAR_DECL) + /* eventually do something */; + } +#endif + + for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp)) + do_type_instantiation (TREE_VALUE (tmp), storage); + } } tree diff --git a/gcc/cp/search.c b/gcc/cp/search.c index c4c6a4e..6623ab4 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1913,6 +1913,10 @@ get_matching_virtual (binfo, fndecl, dtorp) if (IDENTIFIER_VIRTUAL_P (declarator) == 0) return NULL_TREE; + baselink = get_virtuals_named_this (binfo); + if (baselink == NULL_TREE) + return NULL_TREE; + drettype = TREE_TYPE (TREE_TYPE (fndecl)); dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); if (DECL_STATIC_FUNCTION_P (fndecl)) @@ -1920,8 +1924,7 @@ get_matching_virtual (binfo, fndecl, dtorp) else instptr_type = TREE_TYPE (TREE_VALUE (dtypes)); - for (baselink = get_virtuals_named_this (binfo); - baselink; baselink = next_baselink (baselink)) + for (; baselink; baselink = next_baselink (baselink)) { for (tmp = TREE_VALUE (baselink); tmp; tmp = DECL_CHAIN (tmp)) { @@ -1945,7 +1948,7 @@ get_matching_virtual (binfo, fndecl, dtorp) && ! comptypes (TREE_TYPE (TREE_TYPE (tmp)), drettype, 1)) { cp_error ("conflicting return type specified for virtual function `%#D'", fndecl); - cp_error ("overriding definition as `%#D'", tmp); + cp_error_at ("overriding definition as `%#D'", tmp); SET_IDENTIFIER_ERROR_LOCUS (name, basetype); } break; @@ -2697,13 +2700,22 @@ free_mi_matrix () /* If we want debug info for a type TYPE, make sure all its base types are also marked as being potentially interesting. This avoids the problem of not writing any debug info for intermediate basetypes - that have abstract virtual functions. */ + that have abstract virtual functions. Also mark member types. */ void note_debug_info_needed (type) tree type; { + tree field; dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp); + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { + tree ttype; + if (TREE_CODE (field) == FIELD_DECL + && IS_AGGR_TYPE (ttype = target_type (TREE_TYPE (field))) + && dfs_debug_unmarkedp (TYPE_BINFO (ttype))) + note_debug_info_needed (ttype); + } } /* Subroutines of push_class_decls (). */ diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 88466b8..7d92b4e 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -35,66 +35,75 @@ int lvalue_p (ref) tree ref; { - register enum tree_code code = TREE_CODE (ref); + if (! language_lvalue_valid (ref)) + return 0; + + if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) + return 1; - if (language_lvalue_valid (ref)) + if (ref == current_class_decl && flag_this_is_variable <= 0) + return 0; + + switch (TREE_CODE (ref)) { - if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) + /* preincrements and predecrements are valid lvals, provided + what they refer to are valid lvals. */ + case PREINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case COMPONENT_REF: + case SAVE_EXPR: + return lvalue_p (TREE_OPERAND (ref, 0)); + + case STRING_CST: + return 1; + + case VAR_DECL: + if (TREE_READONLY (ref) && ! TREE_STATIC (ref) + && DECL_LANG_SPECIFIC (ref) + && DECL_IN_AGGR_P (ref)) + return 0; + case INDIRECT_REF: + case ARRAY_REF: + case PARM_DECL: + case RESULT_DECL: + case ERROR_MARK: + if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE + && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE) return 1; - - switch (code) - { - /* preincrements and predecrements are valid lvals, provided - what they refer to are valid lvals. */ - case PREINCREMENT_EXPR: - case PREDECREMENT_EXPR: - case COMPONENT_REF: - case SAVE_EXPR: - return lvalue_p (TREE_OPERAND (ref, 0)); - - case STRING_CST: - return 1; - - case VAR_DECL: - if (TREE_READONLY (ref) && ! TREE_STATIC (ref) - && DECL_LANG_SPECIFIC (ref) - && DECL_IN_AGGR_P (ref)) - return 0; - case INDIRECT_REF: - case ARRAY_REF: - case PARM_DECL: - case RESULT_DECL: - case ERROR_MARK: - if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE - && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE) - return 1; - break; + break; - case TARGET_EXPR: - case WITH_CLEANUP_EXPR: - return 1; - - /* A currently unresolved scope ref. */ - case SCOPE_REF: - my_friendly_abort (103); - case OFFSET_REF: - if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL) - return 1; - return lvalue_p (TREE_OPERAND (ref, 0)) - && lvalue_p (TREE_OPERAND (ref, 1)); - break; + case WITH_CLEANUP_EXPR: + return lvalue_p (TREE_OPERAND (ref, 0)); + + case TARGET_EXPR: + return 1; - case COND_EXPR: - return (lvalue_p (TREE_OPERAND (ref, 1)) - && lvalue_p (TREE_OPERAND (ref, 2))); + case CALL_EXPR: + if (TREE_ADDRESSABLE (TREE_TYPE (ref))) + return 1; + break; - case MODIFY_EXPR: - return 1; + /* A currently unresolved scope ref. */ + case SCOPE_REF: + my_friendly_abort (103); + case OFFSET_REF: + if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL) + return 1; + return lvalue_p (TREE_OPERAND (ref, 0)) + && lvalue_p (TREE_OPERAND (ref, 1)); + break; - case COMPOUND_EXPR: - return lvalue_p (TREE_OPERAND (ref, 1)); - } + case COND_EXPR: + return (lvalue_p (TREE_OPERAND (ref, 1)) + && lvalue_p (TREE_OPERAND (ref, 2))); + + case MODIFY_EXPR: + return 1; + + case COMPOUND_EXPR: + return lvalue_p (TREE_OPERAND (ref, 1)); } + return 0; } @@ -1184,50 +1193,6 @@ virtual_member (elem, list) return rval; } -/* Return the offset (as an INTEGER_CST) for ELEM in LIST. - INITIAL_OFFSET is the value to add to the offset that ELEM's - binfo entry in LIST provides. - - Returns NULL if ELEM does not have an binfo value in LIST. */ - -tree -virtual_offset (elem, list, initial_offset) - tree elem; - tree list; - tree initial_offset; -{ - tree vb, offset; - tree rval, nval; - - for (vb = list; vb; vb = TREE_CHAIN (vb)) - if (elem == BINFO_TYPE (vb)) - return size_binop (PLUS_EXPR, initial_offset, BINFO_OFFSET (vb)); - rval = 0; - for (vb = list; vb; vb = TREE_CHAIN (vb)) - { - tree binfos = BINFO_BASETYPES (vb); - int i; - - if (binfos == NULL_TREE) - continue; - - for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--) - { - nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i))); - if (nval) - { - if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval)) - my_friendly_abort (105); - offset = BINFO_OFFSET (vb); - rval = nval; - } - } - } - if (rval == NULL_TREE) - return rval; - return size_binop (PLUS_EXPR, offset, BINFO_OFFSET (rval)); -} - void debug_binfo (elem) tree elem; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index fe8e7ba..a25e143 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1410,8 +1410,19 @@ tree build_object_ref (datum, basetype, field) tree datum, basetype, field; { + tree dtype; if (datum == error_mark_node) return error_mark_node; + + dtype = TREE_TYPE (datum); + if (TREE_CODE (dtype) == REFERENCE_TYPE) + dtype = TREE_TYPE (dtype); + if (! IS_AGGR_TYPE_CODE (TREE_CODE (dtype))) + { + cp_error ("request for member `%T::%D' in expression of non-aggregate type `%T'", + basetype, field, dtype); + return error_mark_node; + } else if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (basetype))) { warning ("signature name in scope resolution ignored"); @@ -3247,6 +3258,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) case GE_EXPR: case LT_EXPR: case GT_EXPR: + result_type = bool_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) short_compare = 1; @@ -3295,7 +3307,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) warning ("comparison between pointer and integer"); op0 = convert (TREE_TYPE (op1), op0); } - result_type = bool_type_node; + else + result_type = 0; converted = 1; break; } @@ -3717,7 +3730,7 @@ build_component_addr (arg, argtype, msg) } else /* This conversion is harmless. */ - rval = convert (argtype, rval); + rval = convert_force (argtype, rval); if (! integer_zerop (DECL_FIELD_BITPOS (field))) { @@ -4939,7 +4952,7 @@ build_c_cast (type, expr) value = TREE_VALUE (value); if (TREE_CODE (type) == VOID_TYPE) - value = build1 (NOP_EXPR, type, value); + value = build1 (CONVERT_EXPR, type, value); else if (TREE_TYPE (value) == NULL_TREE || type_unknown_p (value)) { @@ -6445,7 +6458,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) add_quals = 1; left_const &= TYPE_READONLY (ttl); - if (TREE_CODE (ttl) != POINTER_TYPE) + if (TREE_CODE (ttl) != POINTER_TYPE + || TREE_CODE (ttr) != POINTER_TYPE) break; } unsigned_parity = TREE_UNSIGNED (ttl) - TREE_UNSIGNED (ttr); @@ -7028,6 +7042,7 @@ c_expand_return (retval) && TREE_CODE (TREE_OPERAND (retval, 0)) == TARGET_EXPR) retval = TREE_OPERAND (retval, 0); expand_aggr_init (result, retval, 0); + expand_cleanups_to (NULL_TREE); DECL_INITIAL (result) = NULL_TREE; retval = 0; } @@ -7046,6 +7061,7 @@ c_expand_return (retval) && any_pending_cleanups (1)) { retval = get_temp_regvar (valtype, retval); + expand_cleanups_to (NULL_TREE); use_temp = obey_regdecls; result = 0; } @@ -7071,7 +7087,10 @@ c_expand_return (retval) { /* Everything's great--RETVAL is in RESULT. */ if (original_result_rtx) - store_expr (result, original_result_rtx, 0); + { + store_expr (result, original_result_rtx, 0); + expand_cleanups_to (NULL_TREE); + } else if (retval && retval != result) { /* Clear this out so the later call to decl_function_context @@ -7083,6 +7102,7 @@ c_expand_return (retval) RESULT from cleanups. */ retval = build (INIT_EXPR, TREE_TYPE (result), result, retval); TREE_SIDE_EFFECTS (retval) = 1; + retval = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result), retval); expand_return (retval); } else diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 871173f..87cf58c 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -329,7 +329,7 @@ ack (s, v, v2) silly. So instead, we just do the equivalent of a call to fatal in the same situation (call exit). */ -/* First used: 0 (reserved), Last used: 360. Free: */ +/* First used: 0 (reserved), Last used: 360. Free: 261. */ static int abortcount = 0; -- 2.7.4