aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog95
-rw-r--r--gcc/cp/call.c23
-rw-r--r--gcc/cp/class.c29
-rw-r--r--gcc/cp/cp-tree.h10
-rw-r--r--gcc/cp/decl.c1
-rw-r--r--gcc/cp/decl2.c31
-rw-r--r--gcc/cp/expr.c4
-rw-r--r--gcc/cp/gxxint.texi97
-rw-r--r--gcc/cp/init.c4
-rw-r--r--gcc/cp/lex.c350
-rw-r--r--gcc/cp/method.c4
-rw-r--r--gcc/cp/parse.y1
-rw-r--r--gcc/cp/pt.c26
-rw-r--r--gcc/cp/repo.c70
-rw-r--r--gcc/cp/search.c3
-rw-r--r--gcc/cp/tree.c12
-rw-r--r--gcc/cp/typeck.c70
-rw-r--r--gcc/cp/typeck2.c9
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. */