diff options
-rw-r--r-- | gcc/cp/ChangeLog | 95 | ||||
-rw-r--r-- | gcc/cp/call.c | 23 | ||||
-rw-r--r-- | gcc/cp/class.c | 29 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 10 | ||||
-rw-r--r-- | gcc/cp/decl.c | 1 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 31 | ||||
-rw-r--r-- | gcc/cp/expr.c | 4 | ||||
-rw-r--r-- | gcc/cp/gxxint.texi | 97 | ||||
-rw-r--r-- | gcc/cp/init.c | 4 | ||||
-rw-r--r-- | gcc/cp/lex.c | 350 | ||||
-rw-r--r-- | gcc/cp/method.c | 4 | ||||
-rw-r--r-- | gcc/cp/parse.y | 1 | ||||
-rw-r--r-- | gcc/cp/pt.c | 26 | ||||
-rw-r--r-- | gcc/cp/repo.c | 70 | ||||
-rw-r--r-- | gcc/cp/search.c | 3 | ||||
-rw-r--r-- | gcc/cp/tree.c | 12 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 70 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 9 |
18 files changed, 358 insertions, 481 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bbe5cd7..8670587 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,98 @@ +Sun Apr 23 12:32:38 1995 Mike Stump <mrs@cygnus.com> + + * decl2.c (finish_file): Fix broken linked list handling. + +Fri Apr 21 18:08:43 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * class.c (finish_base_struct): Don't set TYPE_HAS_COMPLEX_*_REF + as often. + (finish_struct): Ditto. + + * various: Use TYPE_HAS_TRIVIAL_* instead of TYPE_HAS_COMPLEX_*. + + * cp-tree.h (TYPE_HAS_TRIVIAL_INIT_REF): New macro. + (TYPE_HAS_TRIVIAL_ASSIGN_REF): New macro. + +Fri Apr 21 15:52:22 1995 Jason Merrill <jason@python.cygnus.com> + + * typeck.c (c_expand_return): Only expand a returned TARGET_EXPR if + it is of the same type as the return value. + +Fri Apr 21 03:01:46 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c (finish_file): Reconsider if synthesizing a method wrote + out its assembly. + + * typeck.c (convert_for_initialization): Don't call a trivial copy + constructor. + + * typeck2.c (store_init_value): Only abort if the type has a + non-trivial copy constructor. + + * typeck.c (c_expand_return): If we're returning in a register and + the return value is a TARGET_EXPR, expand it. Only do + expand_aggr_init if we're returning in memory. + (expand_target_expr): Function to expand a TARGET_EXPR. + (build_modify_expr): Use it. + + * tree.c (build_cplus_new): Layout the slot. + + * expr.c (cplus_expand_expr): Use expand_call to expand the call + under a NEW_EXPR, so the target is not discarded. + +Thu Apr 20 14:59:31 1995 Mike Stump <mrs@cygnus.com> + + * gc.c (build_dynamic_cast): Tighten error checking. + +Thu Apr 20 11:23:54 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * expr.c (cplus_expand_expr): Only abort if the returned target is + different from what we expected if the type has a non-trivial copy + constructor. + + * decl2.c (cplus_decl_attributes): Attributes applied to a template + really apply to the template's result. + + * tree.c (lvalue_p): Check IS_AGGR_TYPE instead of TREE_ADDRESSABLE + to decide whether to consider a CALL_EXPR an lvalue. + + * class.c (finish_struct_bits): Only set TREE_ADDRESSABLE if the + type has a non-trivial copy constructor. + + * decl.c (start_function): If interface_known, unset + DECL_NOT_REALLY_EXTERN on the function. + +Wed Apr 19 16:53:13 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (do_function_instantiation): Handle explicit instantiation of + member functions. + (do_type_instantiation): Handle 'inline template class foo<int>', + meaning just spit out the vtable. + + * lex.c (cons_up_default_function): Set DECL_NOT_REALLY_EXTERN on + the consed functions. + + * decl2.c (import_export_inline): Set DECL_INTERFACE_KNOWN. + +Wed Apr 19 16:28:17 1995 Brendan Kehoe (brendan@lisa.cygnus.com) + + * call.c, class.c, decl2.c, gc.c, init.c, parse.y, pt.c, search.c, + typeck.c: Include output.h. + +Wed Apr 19 14:57:21 1995 Gerald Baumgartner (gb@alexander.cs.purdue.edu) + + * call.c (build_method_call): Allow a signature member functions to + be called from a default implementation. + +Wed Apr 19 10:21:17 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * repo.c (finish_repo): Remember what directory we are in. + + * search.c (expand_upcast_fixups): Don't mess with abort_fndecl. + + * repo.c: Use obstacks instead of fixed-size buffers. Don't spit + out the second copy of the symbol name. Don't remember COLLECT_GCC. + Wed Apr 19 02:32:40 1995 Mike Stump <mrs@cygnus.com> * search.c (virtual_context): New function to get the virtual diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 151d02f..fa92ed8 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -27,6 +27,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include "cp-tree.h" #include "class.h" +#include "output.h" #include "flags.h" #include "obstack.h" @@ -1683,10 +1684,24 @@ build_method_call (instance, name, parms, basetype_path, flags) need_vtbl = (dtor_label || ctor_label) ? unneeded : maybe_needed; - instance = C_C_D; - instance_ptr = current_class_decl; - result = build_field_call (TYPE_BINFO (current_class_type), - instance_ptr, name, parms); + /* If `this' is a signature pointer and `name' is not a constructor, + we are calling a signature member function. In that case, set the + `basetype' to the signature type and dereference the `optr' field. */ + if (IS_SIGNATURE_POINTER (basetype) + && TYPE_IDENTIFIER (basetype) != name) + { + basetype = SIGNATURE_TYPE (basetype); + instance_ptr = build_optr_ref (instance); + instance_ptr = convert (TYPE_POINTER_TO (basetype), instance_ptr); + basetype_path = TYPE_BINFO (basetype); + } + else + { + instance = C_C_D; + instance_ptr = current_class_decl; + basetype_path = TYPE_BINFO (current_class_type); + } + result = build_field_call (basetype_path, instance_ptr, name, parms); if (result) return result; diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 03754bd..78d0c5d 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -27,6 +27,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "cp-tree.h" #include "flags.h" #include "rtl.h" +#include "output.h" #include "obstack.h" #define obstack_chunk_alloc xmalloc @@ -1412,8 +1413,7 @@ finish_base_struct (t, b, t_binfo) TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype); TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype); TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype); - TYPE_HAS_COMPLEX_INIT_REF (t) |= (TYPE_HAS_COMPLEX_INIT_REF (basetype) - || TYPE_NEEDS_CONSTRUCTING (basetype)); + TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype); TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype); TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype); @@ -1688,19 +1688,19 @@ finish_struct_bits (t, max_has_virtual) } } - /* If this type has constructors, force its mode to be BLKmode, - and force its TREE_ADDRESSABLE bit to be nonzero. */ - if (TYPE_NEEDS_CONSTRUCTING (t) || TYPE_NEEDS_DESTRUCTOR (t)) + /* If this type has a copy constructor, force its mode to be BLKmode, and + force its TREE_ADDRESSABLE bit to be nonzero. This will cause it to + be passed by invisible reference and prevent it from being returned in + a register. */ + if (! TYPE_HAS_TRIVIAL_INIT_REF (t)) { - tree variants = t; - + tree variants; if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) DECL_MODE (TYPE_NAME (t)) = BLKmode; - while (variants) + for (variants = t; variants; variants = TYPE_NEXT_VARIANT (variants)) { TYPE_MODE (variants) = BLKmode; TREE_ADDRESSABLE (variants) = 1; - variants = TYPE_NEXT_VARIANT (variants); } } } @@ -3085,7 +3085,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) members. */ cant_synth_asn_ref = 1; cant_have_default_ctor = 1; - TYPE_HAS_COMPLEX_INIT_REF (t) = 1; if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings) { @@ -3109,7 +3108,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) members. */ cant_synth_asn_ref = 1; cant_have_default_ctor = 1; - TYPE_HAS_COMPLEX_INIT_REF (t) = 1; if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t) && extra_warnings) @@ -3266,9 +3264,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type); TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (type); TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type); - TYPE_HAS_COMPLEX_INIT_REF (t) - |= (TYPE_HAS_COMPLEX_INIT_REF (type) - || TYPE_NEEDS_CONSTRUCTING (type)); + TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type); } if (! TYPE_HAS_INIT_REF (type) @@ -3374,7 +3370,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) TYPE_HAS_COMPLEX_INIT_REF (t) |= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) - || has_virtual || any_default_members || first_vfn_base_index >= 0); + || any_default_members); TYPE_NEEDS_CONSTRUCTING (t) |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) || has_virtual || any_default_members || first_vfn_base_index >= 0); @@ -3406,8 +3402,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) TYPE_HAS_REAL_ASSIGNMENT (t) |= TYPE_HAS_ASSIGNMENT (t); TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t); TYPE_HAS_COMPLEX_ASSIGN_REF (t) - |= (TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) - || has_virtual || first_vfn_base_index >= 0); + |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t); if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref && ! IS_SIGNATURE (t)) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a5f761b..22dd9c4 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1220,6 +1220,16 @@ struct lang_decl of ARRAY_TYPE is the type of the elements needs a destructor. */ #define TYPE_NEEDS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_4(NODE)) +/* Nonzero for class type means that initialization of this type can use + a bitwise copy. */ +#define TYPE_HAS_TRIVIAL_INIT_REF(NODE) \ + (TYPE_HAS_INIT_REF (NODE) && ! TYPE_HAS_COMPLEX_INIT_REF (NODE)) + +/* Nonzero for class type means that assignment of this type can use + a bitwise copy. */ +#define TYPE_HAS_TRIVIAL_ASSIGN_REF(NODE) \ + (TYPE_HAS_ASSIGN_REF (NODE) && ! TYPE_HAS_COMPLEX_ASSIGN_REF (NODE)) + /* Nonzero for _TYPE node means that this type is a pointer to member function type. */ #define TYPE_PTRMEMFUNC_P(NODE) (TREE_CODE(NODE) == RECORD_TYPE && TYPE_LANG_SPECIFIC(NODE)->type_flags.ptrmemfunc_flag) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d288048..74dca4f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -10827,6 +10827,7 @@ start_function (declspecs, declarator, raises, pre_parsed_p) || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines)); else DECL_EXTERNAL (decl1) = 0; + DECL_NOT_REALLY_EXTERN (decl1) = 0; DECL_INTERFACE_KNOWN (decl1) = 1; } else diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 7e3528c..5952d85 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -34,6 +34,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "cp-tree.h" #include "decl.h" #include "lex.h" +#include "output.h" extern tree grokdeclarator (); extern tree get_file_function_name (); @@ -1948,8 +1949,13 @@ void cplus_decl_attributes (decl, attributes, prefix_attributes) tree decl, attributes, prefix_attributes; { - if (decl && decl != void_type_node) - decl_attributes (decl, attributes, prefix_attributes); + if (decl == NULL_TREE || decl == void_type_node) + return; + + if (TREE_CODE (decl) == TEMPLATE_DECL) + decl = DECL_TEMPLATE_RESULT (decl); + + decl_attributes (decl, attributes, prefix_attributes); } /* CONSTRUCTOR_NAME: @@ -2775,6 +2781,8 @@ import_export_inline (decl) } else TREE_PUBLIC (decl) = 0; + + DECL_INTERFACE_KNOWN (decl) = 1; } extern int parse_time, varconst_time; @@ -3086,11 +3094,12 @@ finish_file () inline'. */ { int reconsider = 1; /* More may be referenced; check again */ - saved_inlines = tree_cons (NULL_TREE, NULL_TREE, saved_inlines); while (reconsider) { - tree last = saved_inlines; + tree last = saved_inlines = tree_cons (NULL_TREE, NULL_TREE, + saved_inlines); + tree last_head = last; tree place = TREE_CHAIN (saved_inlines); reconsider = 0; @@ -3100,11 +3109,23 @@ finish_file () { tree decl = TREE_VALUE (place); + /* Slice out the empty elements put in just above in the + previous reconsidering. */ + if (decl == NULL_TREE) + { + TREE_CHAIN (last) = TREE_CHAIN (place); + continue; + } + if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)) { if (TREE_USED (decl) || (TREE_PUBLIC (decl) && DECL_NOT_REALLY_EXTERN (decl))) - synthesize_method (decl); + { + synthesize_method (decl); + if (TREE_ASM_WRITTEN (decl)) + reconsider = 1; + } else { last = place; diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index 338065b..c6630cb 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -142,7 +142,7 @@ cplus_expand_expr (exp, target, tmode, modifier) preserve_temp_slots (DECL_RTL (slot)); call_exp = build (CALL_EXPR, type, func, args, 0); TREE_SIDE_EFFECTS (call_exp) = 1; - return_target = expand_expr (call_exp, call_target, mode, 0); + return_target = expand_call (call_exp, call_target, ignore); free_temp_slots (); if (call_target == 0) { @@ -174,7 +174,7 @@ cplus_expand_expr (exp, target, tmode, modifier) if (call_target != return_target) { - my_friendly_assert (! TYPE_NEEDS_CONSTRUCTING (type), 317); + my_friendly_assert (TYPE_HAS_TRIVIAL_INIT_REF (type), 317); if (GET_MODE (return_target) == BLKmode) emit_block_move (call_target, return_target, expr_size (exp), TYPE_ALIGN (type) / BITS_PER_UNIT); diff --git a/gcc/cp/gxxint.texi b/gcc/cp/gxxint.texi index 9be7417..cb3beab 100644 --- a/gcc/cp/gxxint.texi +++ b/gcc/cp/gxxint.texi @@ -1145,16 +1145,21 @@ independent representation for exceptions. The C++ front-end exceptions are mapping into the unwind-protect semantics by the C++ front-end. The mapping is describe below. -Objects with RTTI support should use the RTTI information to do mapping -and checking. Objects without RTTI, like int and const char *, have to -use another means of matching. Currently we use the normal mangling used in -building functions names. Int's are "i", const char * is PCc, etc... - -Unfortunately, the standard allows standard type conversions on throw -parameters so they can match catch handlers. This means we need a -mechanism to handle type conversion at run time, ICK. I read this part -again, and it appears that we only have to be able to do a few of the -conversions at run time, so we should be ok. +When -frtti is used, rtti is used to do exception object type checking, +when it isn't used, the encoded name for the type of the object being +thrown is used instead. All code that originates exceptions, even code +that throws exceptions as a side effect, like dynamic casting, and all +code that catches exceptions must be compiled with either -frtti, or +-fno-rtti. It is not possible to mix rtti base exception handling +objects with code that doesn't use rtti. The exceptions to this, are +code that doesn't catch or throw exceptions, catch (...), and code that +just rethrows an exception. + +Currently we use the normal mangling used in building functions names +(int's are "i", const char * is PCc) to build the non-rtti base type +descriptors for exception handling. These descriptors are just plain +NULL terminated strings, and internally they are passed around as char +*. In C++, all cleanups should be protected by exception regions. The region starts just after the reason why the cleanup is created has @@ -1192,18 +1197,20 @@ throwing. The only bad part, is that the stack remains large. The below points out some flaws in g++'s exception handling, as it now stands. -Only exact type matching or reference matching of throw types works. -Only works on a SPARC machines (like Suns), i386 machines, arm machines -and rs6000 machines. Partial support is also in for alpha, hppa, m68k -and mips machines, but a stack unwinder called __unwind_function has to -be written, and added to libgcc2 for them. All completely constructed -temps and local variables are cleaned up in all unwinded scopes. -Completed parts of partially constructed objects are not cleaned up. -Don't expect exception handling to work right if you optimize, in fact -the compiler will probably core dump. If two EH regions are the exact -same size, the backend cannot tell which one is first. It punts by -picking the last one, if they tie. This is usually right. We really -should stick in a nop, if they are the same size. +Only exact type matching or reference matching of throw types works when +-fno-rtti is used. Only works on a SPARC (like Suns), i386, arm and +rs6000 machines. Partial support is also in for alpha, hppa, m68k and +mips machines, but a stack unwinder called __unwind_function has to be +written, and added to libgcc2 for them. See below for details on +__unwind_function. All completely constructed temps and local variables +are cleaned up in all unwinded scopes. Completed parts of partially +constructed objects are cleaned up with the exception that partially +built arrays are not cleaned up as required. Don't expect exception +handling to work right if you optimize, in fact the compiler will +probably core dump. If two EH regions are the exact same size, the +backend cannot tell which one is first. It punts by picking the last +one, if they tie. This is usually right. We really should stick in a +nop, if they are the same size. When we invoke the copy constructor for an exception object because it is passed by value, and if we take a hit (exception) inside the copy @@ -1232,6 +1239,52 @@ When the backend returns a value, it can create new exception regions that need protecting. The new region should rethrow the object in context of the last associated cleanup that ran to completion. +The __unwind_function takes a pointer to the throw handler, and is +expected to pop the stack frame that was built to call it, as well as +the frame underneath and then jump to the throw handler. It must not +change the three registers allocated for the pointer to the exception +object, the pointer to the type descriptor that identifies the type of +the exception object, and the pointer to the code that threw. On hppa, +these are %r5, %r6, %r7. On m68k these are a2, a3, a4. On mips they +are s0, s1, s2. On Alpha these are $9, $10, $11. It takes about a day +to write this routine, if someone wants to volunteer to write this +routine for any architecture, exception support for that architecture +will be added to g++. Please send in those code donations. + + +The backend must be extended to fully support exceptions. Right now +there are a few hooks into the alpha exception handling backend that +resides in the C++ frontend from that backend that allows exception +handling to work in g++. An exception region is a segment of generated +code that has a handler associated with it. The exception regions are +denoted in the generated code as address ranges denoted by a starting PC +value and an ending PC value of the region. Some of the limitations +with this scheme are: + +@itemize @bullet +@item +The backend replicates insns for such things as loop unrolling and +function inlining. Right now, there are no hooks into the frontend's +exception handling backend to handle the replication of insns. When +replication happens, a new exception region descriptor needs to be +generated for the new region. + +@item +The backend expects to be able to rearrange code, for things like jump +optimization. Any rearranging of the code needs have exception region +descriptors updated appropriately. + +@item +The backend can eliminate dead code. Any associated exception region +descriptor that refers to fully contained code that has been eliminated +should also be removed, although not doing this is harmless in terms of +semantics. + +#end itemize + +The above is not meant to be exhaustive, but does include all things I +have thought of so far. I am sure other limitations exist. + @node Free Store, Concept Index, Exception Handling, Top @section Free Store diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 3ed845c..61ed7e7 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -26,6 +26,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "rtl.h" #include "cp-tree.h" #include "flags.h" +#include "output.h" #undef NULL #define NULL 0 @@ -1202,8 +1203,7 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags) } if (init && TREE_CHAIN (parms) == NULL_TREE - && TYPE_HAS_CONSTRUCTOR (type) - && ! TYPE_NEEDS_CONSTRUCTING (type) + && TYPE_HAS_TRIVIAL_INIT_REF (type) && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init))) { rval = build (INIT_EXPR, type, exp, init); diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index fbf68e4..7c6b791 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -1801,6 +1801,8 @@ cons_up_default_function (type, full_name, kind) || ! flag_implement_inlines); TREE_STATIC (fn) = ! DECL_EXTERNAL (fn); } + else + DECL_NOT_REALLY_EXTERN (fn) = 1; /* When on-the-fly synthesis works properly, remove the second and third conditions here. */ @@ -1849,354 +1851,6 @@ cons_up_default_function (type, full_name, kind) return fn; } -#if 0 -/* Used by default_copy_constructor_body. For the anonymous union - in TYPE, return the member that is at least as large as the rest - of the members, so we can copy it. */ -static tree -largest_union_member (type) - tree type; -{ - tree f, type_size = TYPE_SIZE (type); - - for (f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f)) - if (simple_cst_equal (DECL_SIZE (f), type_size)) - return f; - - /* We should always find one. */ - my_friendly_abort (323); - return NULL_TREE; -} - -/* Construct the body of a default assignment operator. - Mostly copied directly from default_copy_constructor_body. */ -static void -default_assign_ref_body (bufp, lenp, type, fields) - char **bufp; - int *lenp; - tree type, fields; -{ - static struct obstack body; - static int inited = FALSE; - int n_bases = CLASSTYPE_N_BASECLASSES (type); - char *tbuf; - int tgot, tneed; - - if (!inited) - { - obstack_init (&body); - inited = TRUE; - } - body.next_free = body.object_base; - - obstack_1grow (&body, '{'); - - /* Small buffer for sprintf(). */ - - tgot = 100; - tbuf = (char *) alloca (tgot); - - /* If we don't need a real op=, just do a bitwise copy. */ - if (! TYPE_HAS_COMPLEX_ASSIGN_REF (type)) - { - tbuf = "{__builtin_memcpy(this,&_ctor_arg,sizeof(_ctor_arg));return *this;}"; - *lenp = strlen (tbuf); - *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1); - strcpy (*bufp, tbuf); - return; - } - - if (TREE_CODE (type) == UNION_TYPE) - { - if (fields) - { - tree main = fields; - char * s; - tree f; - - for (f = TREE_CHAIN (fields); f; f = TREE_CHAIN (f)) - if (tree_int_cst_lt (TYPE_SIZE (TREE_TYPE (main)), - TYPE_SIZE (TREE_TYPE (f)))) - main = f; - - s = IDENTIFIER_POINTER (DECL_NAME (main)); - - tneed = (2 * strlen (s)) + 28; - if (tgot < tneed) - { - tgot = tneed; - tbuf = (char *) alloca (tgot); - } - - sprintf (tbuf, "{%s=_ctor_arg.%s;return *this;}", s, s); - } - else - tbuf = "{}"; - - *lenp = strlen (tbuf); - *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1); - strcpy (*bufp, tbuf); - return; - } - - /* Construct base classes... - FIXME: Does not deal with multiple inheritance and virtual bases - correctly. See g++.old-deja/g++.jason/opeq5.C for a testcase. - We need to do wacky things if everything between us and the virtual - base (by all paths) has a "complex" op=. */ - - if (n_bases) - { - tree bases = TYPE_BINFO_BASETYPES (type); - int i = 0; - - for (i = 0; i < n_bases; i++) - { - tree binfo = TREE_VEC_ELT (bases, i); - tree btype, name; - char *s; - - btype = BINFO_TYPE (binfo); - name = TYPE_NESTED_NAME (btype); - s = IDENTIFIER_POINTER (name); - - tneed = (2 * strlen (s)) + 42; - if (tgot < tneed) - { - tgot = tneed; - tbuf = (char *) alloca (tgot); - } - - sprintf (tbuf, "%s::operator=((%s%s ::%s&)_ctor_arg);", s, - TYPE_READONLY (type) ? "const " : "", - CLASSTYPE_DECLARED_CLASS (btype) ? "class" : "struct", - s); - obstack_grow (&body, tbuf, strlen (tbuf)); - } - } - - /* Construct fields. */ - - if (fields) - { - tree f; - - for (f = fields; f; f = TREE_CHAIN (f)) - { - if (TREE_CODE (f) == FIELD_DECL && ! DECL_VIRTUAL_P (f)) - { - char *s; - tree x; - tree t = TREE_TYPE (f); - - if (DECL_NAME (f)) - x = f; - else if (t != NULL_TREE - && TREE_CODE (t) == UNION_TYPE - && ((TREE_CODE (TYPE_NAME (t)) == IDENTIFIER_NODE - && ANON_AGGRNAME_P (TYPE_NAME (t))) - || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL - && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))) - && TYPE_FIELDS (t) != NULL_TREE) - x = largest_union_member (t); - else - continue; - - s = IDENTIFIER_POINTER (DECL_NAME (x)); - tneed = (2 * strlen (s)) + 13; - if (tgot < tneed) - { - tgot = tneed; - tbuf = (char *) alloca (tgot); - } - - sprintf (tbuf, "%s=_ctor_arg.%s;", s, s); - obstack_grow (&body, tbuf, strlen (tbuf)); - } - } - } - - obstack_grow (&body, "return *this;}", 15); - - *lenp = obstack_object_size (&body) - 1; - *bufp = obstack_alloc (&inline_text_obstack, *lenp); - - strcpy (*bufp, body.object_base); -} - -/* Construct the body of a default copy constructor. */ -static void -default_copy_constructor_body (bufp, lenp, type, fields) - char **bufp; - int *lenp; - tree type, fields; -{ - static struct obstack prologue; - static int inited = FALSE; - int n_bases = CLASSTYPE_N_BASECLASSES (type); - char sep = ':'; - char *tbuf; - int tgot, tneed; - - /* Create a buffer to call base class constructors and construct members - (fields). */ - - if (!inited) - { - obstack_init (&prologue); - inited = TRUE; - } - prologue.next_free = prologue.object_base; - - /* If we don't need a real copy ctor, just do a bitwise copy. */ - if (! TYPE_HAS_COMPLEX_INIT_REF (type)) - { - tbuf = "{__builtin_memcpy(this,&_ctor_arg,sizeof(_ctor_arg));}"; - *lenp = strlen (tbuf); - *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1); - strcpy (*bufp, tbuf); - return; - } - - /* Small buffer for sprintf(). */ - - tgot = 100; - tbuf = (char *) alloca (tgot); - - if (TREE_CODE (type) == UNION_TYPE) - { - if (fields) - { - tree main = fields; - char * s; - tree f; - - for (f = TREE_CHAIN (fields); f; f = TREE_CHAIN (f)) - if (tree_int_cst_lt (TYPE_SIZE (TREE_TYPE (main)), - TYPE_SIZE (TREE_TYPE (f)))) - main = f; - - s = IDENTIFIER_POINTER (DECL_NAME (main)); - tneed = (2 * strlen (s)) + 16; - if (tgot < tneed) - { - tgot = tneed; - tbuf = (char *) alloca (tgot); - } - - sprintf (tbuf, ":%s(_ctor_arg.%s){}", s, s); - } - else - tbuf = "{}"; - - *lenp = strlen (tbuf); - *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1); - strcpy (*bufp, tbuf); - return; - } - - /* Construct base classes... */ - - if (n_bases) - { - /* Note that CLASSTYPE_VBASECLASSES isn't set yet... */ - tree v = get_vbase_types (type); - tree bases = TYPE_BINFO_BASETYPES (type); - int i = 0; - - for (;;) - { - tree binfo, btype, name; - char *s; - - if (v) - { - binfo = v; - v = TREE_CHAIN (v); - } - else if (i < n_bases) - { - binfo = TREE_VEC_ELT (bases, i++); - if (TREE_VIA_VIRTUAL (binfo)) - continue; - } - else - break; - - btype = BINFO_TYPE (binfo); - name = TYPE_NESTED_NAME (btype); - s = IDENTIFIER_POINTER (name); - - tneed = (2 * strlen (s)) + 39; - if (tgot < tneed) - { - tgot = tneed; - tbuf = (char *) alloca (tgot); - } - - sprintf (tbuf, "%c%s((%s%s ::%s&)_ctor_arg)", sep, s, - TYPE_READONLY (type) ? "const " : "", - CLASSTYPE_DECLARED_CLASS (btype) ? "class" : "struct", - s); - sep = ','; - obstack_grow (&prologue, tbuf, strlen (tbuf)); - } - } - - /* Construct fields. */ - - if (fields) - { - tree f; - - for (f = fields; f; f = TREE_CHAIN (f)) - { - if (TREE_CODE (f) == FIELD_DECL && ! DECL_VIRTUAL_P (f)) - { - char *s; - tree x; - tree t = TREE_TYPE (f); - - if (DECL_NAME (f)) - x = f; - else if (t != NULL_TREE - && TREE_CODE (t) == UNION_TYPE - && ((TREE_CODE (TYPE_NAME (t)) == IDENTIFIER_NODE - && ANON_AGGRNAME_P (TYPE_NAME (t))) - || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL - && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))) - && TYPE_FIELDS (t) != NULL_TREE) - x = largest_union_member (t); - else - continue; - - s = IDENTIFIER_POINTER (DECL_NAME (x)); - tneed = (2 * strlen (s)) + 30; - if (tgot < tneed) - { - tgot = tneed; - tbuf = (char *) alloca (tgot); - } - - sprintf (tbuf, "%c%s(_ctor_arg.%s)", sep, s, s); - sep = ','; - obstack_grow (&prologue, tbuf, strlen (tbuf)); - } - } - } - - /* Concatenate constructor body to prologue. */ - - *lenp = obstack_object_size (&prologue) + 2; - *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1); - - obstack_1grow (&prologue, '\0'); - - strcpy (*bufp, prologue.object_base); - strcat (*bufp, "{}"); -} -#endif - /* Heuristic to tell whether the user is missing a semicolon after a struct or enum declaration. Emit an error message if we know the user has blown it. */ diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 1bf1684..ddf65b1 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -2052,7 +2052,7 @@ do_build_copy_constructor (fndecl) parm = TREE_CHAIN (parm); parm = convert_from_reference (parm); - if (! TYPE_HAS_COMPLEX_INIT_REF (current_class_type)) + if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) { t = build (INIT_EXPR, void_type_node, C_C_D, parm); TREE_SIDE_EFFECTS (t) = 1; @@ -2140,7 +2140,7 @@ do_build_assign_ref (fndecl) parm = convert_from_reference (parm); - if (! TYPE_HAS_COMPLEX_ASSIGN_REF (current_class_type)) + if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) { tree t = build (MODIFY_EXPR, void_type_node, C_C_D, parm); TREE_SIDE_EFFECTS (t) = 1; diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 48c2ae8..46eb2b4 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -53,6 +53,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "flags.h" #include "lex.h" #include "cp-tree.h" +#include "output.h" /* Since parsers are distinct for each language, put the language string definition here. (fnf) */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f7ec05d..9d6266f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -38,6 +38,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "decl.h" #include "parse.h" #include "lex.h" +#include "output.h" extern struct obstack permanent_obstack; extern tree grokdeclarator (); @@ -2510,11 +2511,17 @@ do_function_instantiation (declspecs, declarator, storage) tree declspecs, declarator, storage; { tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, 0); - tree name = DECL_NAME (decl); - tree fn = IDENTIFIER_GLOBAL_VALUE (name); + tree name; + tree fn; tree result = NULL_TREE; int extern_p = 0; - if (fn) + + /* If we've already seen this template instance, use it. */ + if (name = DECL_ASSEMBLER_NAME (decl), + fn = IDENTIFIER_GLOBAL_VALUE (name), + fn && DECL_TEMPLATE_INSTANTIATION (fn)) + result = fn; + else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn) { for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn)) if (decls_match (fn, decl) @@ -2578,12 +2585,14 @@ mark_class_instantiated (t, extern_p) rest_of_type_compilation (t, 1); } } + void do_type_instantiation (name, storage) tree name, storage; { tree t = TREE_TYPE (name); - int extern_p; + int extern_p = 0; + int nomem_p = 0; /* With -fexternal-templates, explicit instantiations are treated the same as implicit ones. */ @@ -2598,7 +2607,9 @@ do_type_instantiation (name, storage) } if (storage == NULL_TREE) - extern_p = 0; + /* OK */; + else if (storage == ridpointers[(int) RID_INLINE]) + nomem_p = 1; else if (storage == ridpointers[(int) RID_EXTERN]) extern_p = 1; else @@ -2618,7 +2629,10 @@ do_type_instantiation (name, storage) mark_class_instantiated (t, extern_p); repo_template_instantiated (t, extern_p); } - + + if (nomem_p) + return; + { tree tmp; /* Classes nested in template classes currently don't have an diff --git a/gcc/cp/repo.c b/gcc/cp/repo.c index 6b5f249..fa04bcd 100644 --- a/gcc/cp/repo.c +++ b/gcc/cp/repo.c @@ -33,14 +33,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ extern char * rindex (); extern char * getenv (); +extern char * getpwd (); static tree pending_repo; static tree original_repo; -static char repo_name[1024]; +static char *repo_name; static FILE *repo_file; extern int flag_use_repository; extern int errorcount, sorrycount; +extern struct obstack temporary_obstack; +extern struct obstack permanent_obstack; #define IDENTIFIER_REPO_USED(NODE) (TREE_LANG_FLAG_3 (NODE)) #define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE)) @@ -187,7 +190,6 @@ save_string (s, len) char *s; int len; { - extern struct obstack temporary_obstack; return obstack_copy0 (&temporary_obstack, s, len); } @@ -244,36 +246,42 @@ open_repo_file (filename) char *filename; { register char *p, *q; - char *file = get_base_filename (filename); - char *s; + char *s = get_base_filename (filename); - if (file == NULL) + if (s == NULL) return; - s = rindex (file, '/'); - if (s == NULL) - s = file; - else - ++s; + p = rindex (s, '/'); + if (! p) + p = s; + p = rindex (p, '.'); + if (! p) + p = s + strlen (s); - for (p = repo_name, q = file; q < s; ) - *p++ = *q++; -/* *p++ = '.'; */ - if ((s = rindex (q, '.')) == NULL) - strcpy (p, q); - else - for (; q < s;) - *p++ = *q++; - strcat (p, ".rpo"); + obstack_grow (&permanent_obstack, s, p - s); + repo_name = obstack_copy0 (&permanent_obstack, ".rpo", 4); repo_file = fopen (repo_name, "r"); } +static char * +afgets (stream) + FILE *stream; +{ + int c; + while ((c = getc (stream)) != EOF && c != '\n') + obstack_1grow (&temporary_obstack, c); + if (obstack_object_size (&temporary_obstack) == 0) + return NULL; + obstack_1grow (&temporary_obstack, '\0'); + return obstack_finish (&temporary_obstack); +} + void init_repo (filename) char *filename; { - char buf[1024]; + char *buf; if (! flag_use_repository) return; @@ -283,23 +291,19 @@ init_repo (filename) if (repo_file == 0) return; - while (fgets (buf, 1024, repo_file)) + while (buf = afgets (repo_file)) { switch (buf[0]) { case 'A': - case 'G': + case 'D': case 'M': break; case 'C': case 'O': { - char *q; - tree id, orig; - - for (q = &buf[2]; *q && *q != ' ' && *q != '\n'; ++q) ; - q = save_string (&buf[2], q - &buf[2]); - id = get_identifier (q); + tree id = get_identifier (buf + 2); + tree orig; if (buf[0] == 'C') { @@ -315,6 +319,7 @@ init_repo (filename) default: error ("mysterious repository information in %s", repo_name); } + obstack_free (&temporary_obstack, buf); } } @@ -382,9 +387,8 @@ finish_repo () fprintf (repo_file, "M %s\n", main_input_filename); - p = getenv ("COLLECT_GCC"); - if (p != 0) - fprintf (repo_file, "G %s\n", p); + p = getpwd (); + fprintf (repo_file, "D %s\n", p); p = getenv ("COLLECT_GCC_OPTIONS"); if (p != 0) @@ -395,9 +399,7 @@ finish_repo () tree val = TREE_VALUE (t); char type = IDENTIFIER_REPO_CHOSEN (val) ? 'C' : 'O'; - fprintf (repo_file, "%c %s ", type, IDENTIFIER_POINTER (val)); - ASM_OUTPUT_LABELREF (repo_file, IDENTIFIER_POINTER (val)); - putc ('\n', repo_file); + fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (val)); } out: diff --git a/gcc/cp/search.c b/gcc/cp/search.c index dfa2315..c586835 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -28,12 +28,14 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "obstack.h" #include "flags.h" #include "rtl.h" +#include "output.h" #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free void init_search (); extern struct obstack *current_obstack; +extern tree abort_fndecl; #include "stack.h" @@ -2626,6 +2628,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets) current_fndecl = FNADDR_FROM_VTABLE_ENTRY (current_fndecl); current_fndecl = TREE_OPERAND (current_fndecl, 0); if (current_fndecl + && current_fndecl != abort_fndecl && (vc=virtual_context (current_fndecl, t, vbase)) != vbase) { /* This may in fact need a runtime fixup. */ diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 90c21b2..196f1a4 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -153,7 +153,7 @@ lvalue_p (ref) return 1; case CALL_EXPR: - if (TREE_ADDRESSABLE (TREE_TYPE (ref))) + if (IS_AGGR_TYPE (TREE_TYPE (ref))) return 1; break; @@ -217,9 +217,13 @@ build_cplus_new (type, init, with_cleanup_p) tree init; int with_cleanup_p; { - tree slot = build (VAR_DECL, type); - tree rval = build (NEW_EXPR, type, - TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot); + tree slot; + tree rval; + + slot = build (VAR_DECL, type); + layout_decl (slot, 0); + rval = build (NEW_EXPR, type, + TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot); TREE_SIDE_EFFECTS (rval) = 1; TREE_ADDRESSABLE (rval) = 1; rval = build (TARGET_EXPR, type, slot, rval, 0); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 0384d7a..71846da 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -37,6 +37,7 @@ extern void warning (); #include "rtl.h" #include "cp-tree.h" #include "flags.h" +#include "output.h" int mark_addressable (); static tree convert_for_assignment (); @@ -2665,8 +2666,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) /* Convert `float' to `double'. */ result = tree_cons (NULL_TREE, convert (double_type_node, val), result); else if (TYPE_LANG_SPECIFIC (TREE_TYPE (val)) - && (! TYPE_HAS_INIT_REF (TREE_TYPE (val)) - || TYPE_HAS_COMPLEX_INIT_REF (TREE_TYPE (val)))) + && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val))) { cp_warning ("cannot pass objects of type `%T' through `...'", TREE_TYPE (val)); @@ -5454,6 +5454,26 @@ init_noncopied_parts (lhs, list) return parts; } +tree +expand_target_expr (t) + tree t; +{ + tree xval = make_node (RTL_EXPR); + rtx rtxval; + + do_pending_stack_adjust (); + start_sequence_for_rtl_expr (xval); + emit_note (0, -1); + rtxval = expand_expr (t, NULL, VOIDmode, 0); + do_pending_stack_adjust (); + TREE_SIDE_EFFECTS (xval) = 1; + RTL_EXPR_SEQUENCE (xval) = get_insns (); + end_sequence (); + RTL_EXPR_RTL (xval) = rtxval; + TREE_TYPE (xval) = TREE_TYPE (t); + return xval; +} + /* Build an assignment expression of lvalue LHS from value RHS. MODIFYCODE is the code for a binary operator that we use to combine the old value of LHS with RHS to get the new value. @@ -5586,7 +5606,7 @@ build_modify_expr (lhs, modifycode, rhs) /* Do the default thing */; else if (! TYPE_HAS_CONSTRUCTOR (lhstype)) cp_error ("`%T' has no constructors", lhstype); - else if (! TYPE_NEEDS_CONSTRUCTING (lhstype) + else if (TYPE_HAS_TRIVIAL_INIT_REF (lhstype) && TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs))) /* Do the default thing */; else @@ -5607,8 +5627,7 @@ build_modify_expr (lhs, modifycode, rhs) /* Do the default thing */; else if (! TYPE_HAS_ASSIGNMENT (lhstype)) cp_error ("`%T' does not define operator=", lhstype); - else if (! TYPE_HAS_REAL_ASSIGNMENT (lhstype) - && ! TYPE_HAS_COMPLEX_ASSIGN_REF (lhstype) + else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (lhstype) && TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs))) /* Do the default thing */; else @@ -6002,28 +6021,12 @@ build_modify_expr (lhs, modifycode, rhs) && TYPE_NEEDS_CONSTRUCTING (lhstype)) newrhs = build_cplus_new (lhstype, newrhs, 0); + /* Can't initialize directly from a TARGET_EXPR, since that would + cause the lhs to be constructed twice. So we force the + TARGET_EXPR to be expanded. expand_expr should really do this + by itself. */ if (TREE_CODE (newrhs) == TARGET_EXPR) - { - /* Can't initialize directly from a TARGET_EXPR, since that would - cause the lhs to be constructed twice. So we force the - TARGET_EXPR to be expanded. expand_expr should really do this - by itself. */ - - tree xval = make_node (RTL_EXPR); - rtx rtxval; - - do_pending_stack_adjust (); - start_sequence_for_rtl_expr (xval); - emit_note (0, -1); - rtxval = expand_expr (newrhs, NULL, VOIDmode, 0); - do_pending_stack_adjust (); - TREE_SIDE_EFFECTS (xval) = 1; - RTL_EXPR_SEQUENCE (xval) = get_insns (); - end_sequence (); - RTL_EXPR_RTL (xval) = rtxval; - TREE_TYPE (xval) = lhstype; - newrhs = xval; - } + newrhs = expand_target_expr (newrhs); } if (TREE_CODE (newrhs) == ERROR_MARK) @@ -6964,6 +6967,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) rhs = build_cplus_new (type, TREE_OPERAND (rhs, 0), 0); return rhs; } + else if (TYPE_HAS_TRIVIAL_INIT_REF (type)) + return rhs; } if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype) || (IS_AGGR_TYPE (rhstype) && UNIQUELY_DERIVED_FROM_P (type, rhstype))) @@ -7227,6 +7232,13 @@ c_expand_return (retval) (3) If an X(X&) constructor is defined, the return value must be returned via that. */ + /* If we're returning in a register, we can't initialize the + return value from a TARGET_EXPR. */ + if (TREE_CODE (retval) == TARGET_EXPR + && TYPE_MAIN_VARIANT (TREE_TYPE (retval)) == TYPE_MAIN_VARIANT (valtype) + && ! current_function_returns_struct) + retval = expand_target_expr (retval); + if (retval == result /* Watch out for constructors, which "return" aggregates via initialization, but which otherwise "return" a pointer. */ @@ -7243,12 +7255,8 @@ c_expand_return (retval) use_temp = obey_regdecls; } } - else if (IS_AGGR_TYPE (valtype) && TYPE_NEEDS_CONSTRUCTING (valtype)) + else if (IS_AGGR_TYPE (valtype) && current_function_returns_struct) { - /* Throw away the cleanup that `build_functional_cast' gave us. */ - if (TREE_CODE (retval) == WITH_CLEANUP_EXPR - && TREE_CODE (TREE_OPERAND (retval, 0)) == TARGET_EXPR) - retval = TREE_OPERAND (retval, 0); expand_aggr_init (result, retval, 0, LOOKUP_ONLYCONVERTING); expand_cleanups_to (NULL_TREE); DECL_INITIAL (result) = NULL_TREE; diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 98cc90d..1c719aa 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -540,11 +540,12 @@ store_init_value (decl, init) /* Take care of C++ business up here. */ type = TYPE_MAIN_VARIANT (type); - /* implicitly tests if IS_AGGR_TYPE. */ - if (TYPE_NEEDS_CONSTRUCTING (type) && TREE_CODE (init) != CONSTRUCTOR) - my_friendly_abort (109); - else if (IS_AGGR_TYPE (type)) + if (IS_AGGR_TYPE (type)) { + if (! TYPE_HAS_TRIVIAL_INIT_REF (type) + && TREE_CODE (init) != CONSTRUCTOR) + my_friendly_abort (109); + /* Although we are not allowed to declare variables of signature type, we complain about a possible constructor call in such a declaration as well. */ |