Commit e8abc66f by Mike Stump

67th Cygnus<->FSF merge

From-SVN: r9433
parent 87c73618
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> Wed Apr 19 02:32:40 1995 Mike Stump <mrs@cygnus.com>
* search.c (virtual_context): New function to get the virtual * search.c (virtual_context): New function to get the virtual
......
...@@ -27,6 +27,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -27,6 +27,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h> #include <stdio.h>
#include "cp-tree.h" #include "cp-tree.h"
#include "class.h" #include "class.h"
#include "output.h"
#include "flags.h" #include "flags.h"
#include "obstack.h" #include "obstack.h"
...@@ -1683,10 +1684,24 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -1683,10 +1684,24 @@ build_method_call (instance, name, parms, basetype_path, flags)
need_vtbl = (dtor_label || ctor_label) need_vtbl = (dtor_label || ctor_label)
? unneeded : maybe_needed; ? unneeded : maybe_needed;
/* 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 = C_C_D;
instance_ptr = current_class_decl; instance_ptr = current_class_decl;
result = build_field_call (TYPE_BINFO (current_class_type), basetype_path = TYPE_BINFO (current_class_type);
instance_ptr, name, parms); }
result = build_field_call (basetype_path, instance_ptr, name, parms);
if (result) if (result)
return result; return result;
......
...@@ -27,6 +27,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -27,6 +27,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "cp-tree.h" #include "cp-tree.h"
#include "flags.h" #include "flags.h"
#include "rtl.h" #include "rtl.h"
#include "output.h"
#include "obstack.h" #include "obstack.h"
#define obstack_chunk_alloc xmalloc #define obstack_chunk_alloc xmalloc
...@@ -1412,8 +1413,7 @@ finish_base_struct (t, b, t_binfo) ...@@ -1412,8 +1413,7 @@ finish_base_struct (t, b, t_binfo)
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype); TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype); TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype);
TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (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_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype);
|| TYPE_NEEDS_CONSTRUCTING (basetype));
TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype); TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype);
TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype); TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
...@@ -1688,19 +1688,19 @@ finish_struct_bits (t, max_has_virtual) ...@@ -1688,19 +1688,19 @@ finish_struct_bits (t, max_has_virtual)
} }
} }
/* If this type has constructors, force its mode to be BLKmode, /* If this type has a copy constructor, force its mode to be BLKmode, and
and force its TREE_ADDRESSABLE bit to be nonzero. */ force its TREE_ADDRESSABLE bit to be nonzero. This will cause it to
if (TYPE_NEEDS_CONSTRUCTING (t) || TYPE_NEEDS_DESTRUCTOR (t)) 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) if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)
DECL_MODE (TYPE_NAME (t)) = BLKmode; DECL_MODE (TYPE_NAME (t)) = BLKmode;
while (variants) for (variants = t; variants; variants = TYPE_NEXT_VARIANT (variants))
{ {
TYPE_MODE (variants) = BLKmode; TYPE_MODE (variants) = BLKmode;
TREE_ADDRESSABLE (variants) = 1; TREE_ADDRESSABLE (variants) = 1;
variants = TYPE_NEXT_VARIANT (variants);
} }
} }
} }
...@@ -3085,7 +3085,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3085,7 +3085,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
members. */ members. */
cant_synth_asn_ref = 1; cant_synth_asn_ref = 1;
cant_have_default_ctor = 1; cant_have_default_ctor = 1;
TYPE_HAS_COMPLEX_INIT_REF (t) = 1;
if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings) if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
{ {
...@@ -3109,7 +3108,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3109,7 +3108,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
members. */ members. */
cant_synth_asn_ref = 1; cant_synth_asn_ref = 1;
cant_have_default_ctor = 1; cant_have_default_ctor = 1;
TYPE_HAS_COMPLEX_INIT_REF (t) = 1;
if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t) if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t)
&& extra_warnings) && extra_warnings)
...@@ -3266,9 +3264,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3266,9 +3264,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type); TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type);
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (type); TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (type);
TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type); TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type);
TYPE_HAS_COMPLEX_INIT_REF (t) TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
|= (TYPE_HAS_COMPLEX_INIT_REF (type)
|| TYPE_NEEDS_CONSTRUCTING (type));
} }
if (! TYPE_HAS_INIT_REF (type) if (! TYPE_HAS_INIT_REF (type)
...@@ -3374,7 +3370,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3374,7 +3370,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
TYPE_HAS_COMPLEX_INIT_REF (t) TYPE_HAS_COMPLEX_INIT_REF (t)
|= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (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_NEEDS_CONSTRUCTING (t)
|= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t)
|| has_virtual || any_default_members || first_vfn_base_index >= 0); || has_virtual || any_default_members || first_vfn_base_index >= 0);
...@@ -3406,8 +3402,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -3406,8 +3402,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
TYPE_HAS_REAL_ASSIGNMENT (t) |= TYPE_HAS_ASSIGNMENT (t); TYPE_HAS_REAL_ASSIGNMENT (t) |= TYPE_HAS_ASSIGNMENT (t);
TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t); TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
TYPE_HAS_COMPLEX_ASSIGN_REF (t) TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= (TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t);
|| has_virtual || first_vfn_base_index >= 0);
if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref
&& ! IS_SIGNATURE (t)) && ! IS_SIGNATURE (t))
......
...@@ -1220,6 +1220,16 @@ struct lang_decl ...@@ -1220,6 +1220,16 @@ struct lang_decl
of ARRAY_TYPE is the type of the elements needs a destructor. */ of ARRAY_TYPE is the type of the elements needs a destructor. */
#define TYPE_NEEDS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_4(NODE)) #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 /* Nonzero for _TYPE node means that this type is a pointer to member
function type. */ function type. */
#define TYPE_PTRMEMFUNC_P(NODE) (TREE_CODE(NODE) == RECORD_TYPE && TYPE_LANG_SPECIFIC(NODE)->type_flags.ptrmemfunc_flag) #define TYPE_PTRMEMFUNC_P(NODE) (TREE_CODE(NODE) == RECORD_TYPE && TYPE_LANG_SPECIFIC(NODE)->type_flags.ptrmemfunc_flag)
......
...@@ -10827,6 +10827,7 @@ start_function (declspecs, declarator, raises, pre_parsed_p) ...@@ -10827,6 +10827,7 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
|| (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines)); || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines));
else else
DECL_EXTERNAL (decl1) = 0; DECL_EXTERNAL (decl1) = 0;
DECL_NOT_REALLY_EXTERN (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1; DECL_INTERFACE_KNOWN (decl1) = 1;
} }
else else
......
...@@ -34,6 +34,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -34,6 +34,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "cp-tree.h" #include "cp-tree.h"
#include "decl.h" #include "decl.h"
#include "lex.h" #include "lex.h"
#include "output.h"
extern tree grokdeclarator (); extern tree grokdeclarator ();
extern tree get_file_function_name (); extern tree get_file_function_name ();
...@@ -1948,7 +1949,12 @@ void ...@@ -1948,7 +1949,12 @@ void
cplus_decl_attributes (decl, attributes, prefix_attributes) cplus_decl_attributes (decl, attributes, prefix_attributes)
tree decl, attributes, prefix_attributes; tree decl, attributes, prefix_attributes;
{ {
if (decl && decl != void_type_node) 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); decl_attributes (decl, attributes, prefix_attributes);
} }
...@@ -2775,6 +2781,8 @@ import_export_inline (decl) ...@@ -2775,6 +2781,8 @@ import_export_inline (decl)
} }
else else
TREE_PUBLIC (decl) = 0; TREE_PUBLIC (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;
} }
extern int parse_time, varconst_time; extern int parse_time, varconst_time;
...@@ -3086,11 +3094,12 @@ finish_file () ...@@ -3086,11 +3094,12 @@ finish_file ()
inline'. */ inline'. */
{ {
int reconsider = 1; /* More may be referenced; check again */ int reconsider = 1; /* More may be referenced; check again */
saved_inlines = tree_cons (NULL_TREE, NULL_TREE, saved_inlines);
while (reconsider) 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); tree place = TREE_CHAIN (saved_inlines);
reconsider = 0; reconsider = 0;
...@@ -3100,11 +3109,23 @@ finish_file () ...@@ -3100,11 +3109,23 @@ finish_file ()
{ {
tree decl = TREE_VALUE (place); 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 (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl))
{ {
if (TREE_USED (decl) if (TREE_USED (decl)
|| (TREE_PUBLIC (decl) && DECL_NOT_REALLY_EXTERN (decl))) || (TREE_PUBLIC (decl) && DECL_NOT_REALLY_EXTERN (decl)))
{
synthesize_method (decl); synthesize_method (decl);
if (TREE_ASM_WRITTEN (decl))
reconsider = 1;
}
else else
{ {
last = place; last = place;
......
...@@ -142,7 +142,7 @@ cplus_expand_expr (exp, target, tmode, modifier) ...@@ -142,7 +142,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
preserve_temp_slots (DECL_RTL (slot)); preserve_temp_slots (DECL_RTL (slot));
call_exp = build (CALL_EXPR, type, func, args, 0); call_exp = build (CALL_EXPR, type, func, args, 0);
TREE_SIDE_EFFECTS (call_exp) = 1; 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 (); free_temp_slots ();
if (call_target == 0) if (call_target == 0)
{ {
...@@ -174,7 +174,7 @@ cplus_expand_expr (exp, target, tmode, modifier) ...@@ -174,7 +174,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
if (call_target != return_target) 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) if (GET_MODE (return_target) == BLKmode)
emit_block_move (call_target, return_target, expr_size (exp), emit_block_move (call_target, return_target, expr_size (exp),
TYPE_ALIGN (type) / BITS_PER_UNIT); TYPE_ALIGN (type) / BITS_PER_UNIT);
......
...@@ -1145,16 +1145,21 @@ independent representation for exceptions. ...@@ -1145,16 +1145,21 @@ independent representation for exceptions.
The C++ front-end exceptions are mapping into the unwind-protect The C++ front-end exceptions are mapping into the unwind-protect
semantics by the C++ front-end. The mapping is describe below. semantics by the C++ front-end. The mapping is describe below.
Objects with RTTI support should use the RTTI information to do mapping When -frtti is used, rtti is used to do exception object type checking,
and checking. Objects without RTTI, like int and const char *, have to when it isn't used, the encoded name for the type of the object being
use another means of matching. Currently we use the normal mangling used in thrown is used instead. All code that originates exceptions, even code
building functions names. Int's are "i", const char * is PCc, etc... that throws exceptions as a side effect, like dynamic casting, and all
code that catches exceptions must be compiled with either -frtti, or
Unfortunately, the standard allows standard type conversions on throw -fno-rtti. It is not possible to mix rtti base exception handling
parameters so they can match catch handlers. This means we need a objects with code that doesn't use rtti. The exceptions to this, are
mechanism to handle type conversion at run time, ICK. I read this part code that doesn't catch or throw exceptions, catch (...), and code that
again, and it appears that we only have to be able to do a few of the just rethrows an exception.
conversions at run time, so we should be ok.
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 In C++, all cleanups should be protected by exception regions. The
region starts just after the reason why the cleanup is created has 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. ...@@ -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 The below points out some flaws in g++'s exception handling, as it now
stands. stands.
Only exact type matching or reference matching of throw types works. Only exact type matching or reference matching of throw types works when
Only works on a SPARC machines (like Suns), i386 machines, arm machines -fno-rtti is used. Only works on a SPARC (like Suns), i386, arm and
and rs6000 machines. Partial support is also in for alpha, hppa, m68k rs6000 machines. Partial support is also in for alpha, hppa, m68k and
and mips machines, but a stack unwinder called __unwind_function has to mips machines, but a stack unwinder called __unwind_function has to be
be written, and added to libgcc2 for them. All completely constructed written, and added to libgcc2 for them. See below for details on
temps and local variables are cleaned up in all unwinded scopes. __unwind_function. All completely constructed temps and local variables
Completed parts of partially constructed objects are not cleaned up. are cleaned up in all unwinded scopes. Completed parts of partially
Don't expect exception handling to work right if you optimize, in fact constructed objects are cleaned up with the exception that partially
the compiler will probably core dump. If two EH regions are the exact built arrays are not cleaned up as required. Don't expect exception
same size, the backend cannot tell which one is first. It punts by handling to work right if you optimize, in fact the compiler will
picking the last one, if they tie. This is usually right. We really probably core dump. If two EH regions are the exact same size, the
should stick in a nop, if they are the same size. 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 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 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 ...@@ -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 that need protecting. The new region should rethrow the object in
context of the last associated cleanup that ran to completion. 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 @node Free Store, Concept Index, Exception Handling, Top
@section Free Store @section Free Store
......
...@@ -26,6 +26,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -26,6 +26,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "rtl.h" #include "rtl.h"
#include "cp-tree.h" #include "cp-tree.h"
#include "flags.h" #include "flags.h"
#include "output.h"
#undef NULL #undef NULL
#define NULL 0 #define NULL 0
...@@ -1202,8 +1203,7 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags) ...@@ -1202,8 +1203,7 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
} }
if (init && TREE_CHAIN (parms) == NULL_TREE if (init && TREE_CHAIN (parms) == NULL_TREE
&& TYPE_HAS_CONSTRUCTOR (type) && TYPE_HAS_TRIVIAL_INIT_REF (type)
&& ! TYPE_NEEDS_CONSTRUCTING (type)
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init))) && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
{ {
rval = build (INIT_EXPR, type, exp, init); rval = build (INIT_EXPR, type, exp, init);
......
...@@ -1801,6 +1801,8 @@ cons_up_default_function (type, full_name, kind) ...@@ -1801,6 +1801,8 @@ cons_up_default_function (type, full_name, kind)
|| ! flag_implement_inlines); || ! flag_implement_inlines);
TREE_STATIC (fn) = ! DECL_EXTERNAL (fn); 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 /* When on-the-fly synthesis works properly, remove the second and third
conditions here. */ conditions here. */
...@@ -1849,354 +1851,6 @@ cons_up_default_function (type, full_name, kind) ...@@ -1849,354 +1851,6 @@ cons_up_default_function (type, full_name, kind)
return fn; 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 /* Heuristic to tell whether the user is missing a semicolon
after a struct or enum declaration. Emit an error message after a struct or enum declaration. Emit an error message
if we know the user has blown it. */ if we know the user has blown it. */
......
...@@ -2052,7 +2052,7 @@ do_build_copy_constructor (fndecl) ...@@ -2052,7 +2052,7 @@ do_build_copy_constructor (fndecl)
parm = TREE_CHAIN (parm); parm = TREE_CHAIN (parm);
parm = convert_from_reference (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); t = build (INIT_EXPR, void_type_node, C_C_D, parm);
TREE_SIDE_EFFECTS (t) = 1; TREE_SIDE_EFFECTS (t) = 1;
...@@ -2140,7 +2140,7 @@ do_build_assign_ref (fndecl) ...@@ -2140,7 +2140,7 @@ do_build_assign_ref (fndecl)
parm = convert_from_reference (parm); 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 t = build (MODIFY_EXPR, void_type_node, C_C_D, parm);
TREE_SIDE_EFFECTS (t) = 1; TREE_SIDE_EFFECTS (t) = 1;
......
...@@ -53,6 +53,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -53,6 +53,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "flags.h" #include "flags.h"
#include "lex.h" #include "lex.h"
#include "cp-tree.h" #include "cp-tree.h"
#include "output.h"
/* Since parsers are distinct for each language, put the language string /* Since parsers are distinct for each language, put the language string
definition here. (fnf) */ definition here. (fnf) */
......
...@@ -38,6 +38,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -38,6 +38,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "decl.h" #include "decl.h"
#include "parse.h" #include "parse.h"
#include "lex.h" #include "lex.h"
#include "output.h"
extern struct obstack permanent_obstack; extern struct obstack permanent_obstack;
extern tree grokdeclarator (); extern tree grokdeclarator ();
...@@ -2510,11 +2511,17 @@ do_function_instantiation (declspecs, declarator, storage) ...@@ -2510,11 +2511,17 @@ do_function_instantiation (declspecs, declarator, storage)
tree declspecs, declarator, storage; tree declspecs, declarator, storage;
{ {
tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, 0); tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, 0);
tree name = DECL_NAME (decl); tree name;
tree fn = IDENTIFIER_GLOBAL_VALUE (name); tree fn;
tree result = NULL_TREE; tree result = NULL_TREE;
int extern_p = 0; 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)) for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
if (decls_match (fn, decl) if (decls_match (fn, decl)
...@@ -2578,12 +2585,14 @@ mark_class_instantiated (t, extern_p) ...@@ -2578,12 +2585,14 @@ mark_class_instantiated (t, extern_p)
rest_of_type_compilation (t, 1); rest_of_type_compilation (t, 1);
} }
} }
void void
do_type_instantiation (name, storage) do_type_instantiation (name, storage)
tree name, storage; tree name, storage;
{ {
tree t = TREE_TYPE (name); 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 /* With -fexternal-templates, explicit instantiations are treated the same
as implicit ones. */ as implicit ones. */
...@@ -2598,7 +2607,9 @@ do_type_instantiation (name, storage) ...@@ -2598,7 +2607,9 @@ do_type_instantiation (name, storage)
} }
if (storage == NULL_TREE) 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]) else if (storage == ridpointers[(int) RID_EXTERN])
extern_p = 1; extern_p = 1;
else else
...@@ -2619,6 +2630,9 @@ do_type_instantiation (name, storage) ...@@ -2619,6 +2630,9 @@ do_type_instantiation (name, storage)
repo_template_instantiated (t, extern_p); repo_template_instantiated (t, extern_p);
} }
if (nomem_p)
return;
{ {
tree tmp; tree tmp;
/* Classes nested in template classes currently don't have an /* Classes nested in template classes currently don't have an
......
...@@ -33,14 +33,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -33,14 +33,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
extern char * rindex (); extern char * rindex ();
extern char * getenv (); extern char * getenv ();
extern char * getpwd ();
static tree pending_repo; static tree pending_repo;
static tree original_repo; static tree original_repo;
static char repo_name[1024]; static char *repo_name;
static FILE *repo_file; static FILE *repo_file;
extern int flag_use_repository; extern int flag_use_repository;
extern int errorcount, sorrycount; 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_USED(NODE) (TREE_LANG_FLAG_3 (NODE))
#define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE)) #define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
...@@ -187,7 +190,6 @@ save_string (s, len) ...@@ -187,7 +190,6 @@ save_string (s, len)
char *s; char *s;
int len; int len;
{ {
extern struct obstack temporary_obstack;
return obstack_copy0 (&temporary_obstack, s, len); return obstack_copy0 (&temporary_obstack, s, len);
} }
...@@ -244,36 +246,42 @@ open_repo_file (filename) ...@@ -244,36 +246,42 @@ open_repo_file (filename)
char *filename; char *filename;
{ {
register char *p, *q; register char *p, *q;
char *file = get_base_filename (filename); char *s = get_base_filename (filename);
char *s;
if (file == NULL) if (s == NULL)
return; return;
s = rindex (file, '/'); p = rindex (s, '/');
if (s == NULL) if (! p)
s = file; p = s;
else p = rindex (p, '.');
++s; if (! p)
p = s + strlen (s);
for (p = repo_name, q = file; q < s; ) obstack_grow (&permanent_obstack, s, p - s);
*p++ = *q++; repo_name = obstack_copy0 (&permanent_obstack, ".rpo", 4);
/* *p++ = '.'; */
if ((s = rindex (q, '.')) == NULL)
strcpy (p, q);
else
for (; q < s;)
*p++ = *q++;
strcat (p, ".rpo");
repo_file = fopen (repo_name, "r"); 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 void
init_repo (filename) init_repo (filename)
char *filename; char *filename;
{ {
char buf[1024]; char *buf;
if (! flag_use_repository) if (! flag_use_repository)
return; return;
...@@ -283,23 +291,19 @@ init_repo (filename) ...@@ -283,23 +291,19 @@ init_repo (filename)
if (repo_file == 0) if (repo_file == 0)
return; return;
while (fgets (buf, 1024, repo_file)) while (buf = afgets (repo_file))
{ {
switch (buf[0]) switch (buf[0])
{ {
case 'A': case 'A':
case 'G': case 'D':
case 'M': case 'M':
break; break;
case 'C': case 'C':
case 'O': case 'O':
{ {
char *q; tree id = get_identifier (buf + 2);
tree id, orig; tree orig;
for (q = &buf[2]; *q && *q != ' ' && *q != '\n'; ++q) ;
q = save_string (&buf[2], q - &buf[2]);
id = get_identifier (q);
if (buf[0] == 'C') if (buf[0] == 'C')
{ {
...@@ -315,6 +319,7 @@ init_repo (filename) ...@@ -315,6 +319,7 @@ init_repo (filename)
default: default:
error ("mysterious repository information in %s", repo_name); error ("mysterious repository information in %s", repo_name);
} }
obstack_free (&temporary_obstack, buf);
} }
} }
...@@ -382,9 +387,8 @@ finish_repo () ...@@ -382,9 +387,8 @@ finish_repo ()
fprintf (repo_file, "M %s\n", main_input_filename); fprintf (repo_file, "M %s\n", main_input_filename);
p = getenv ("COLLECT_GCC"); p = getpwd ();
if (p != 0) fprintf (repo_file, "D %s\n", p);
fprintf (repo_file, "G %s\n", p);
p = getenv ("COLLECT_GCC_OPTIONS"); p = getenv ("COLLECT_GCC_OPTIONS");
if (p != 0) if (p != 0)
...@@ -395,9 +399,7 @@ finish_repo () ...@@ -395,9 +399,7 @@ finish_repo ()
tree val = TREE_VALUE (t); tree val = TREE_VALUE (t);
char type = IDENTIFIER_REPO_CHOSEN (val) ? 'C' : 'O'; char type = IDENTIFIER_REPO_CHOSEN (val) ? 'C' : 'O';
fprintf (repo_file, "%c %s ", type, IDENTIFIER_POINTER (val)); fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (val));
ASM_OUTPUT_LABELREF (repo_file, IDENTIFIER_POINTER (val));
putc ('\n', repo_file);
} }
out: out:
......
...@@ -28,12 +28,14 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -28,12 +28,14 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "obstack.h" #include "obstack.h"
#include "flags.h" #include "flags.h"
#include "rtl.h" #include "rtl.h"
#include "output.h"
#define obstack_chunk_alloc xmalloc #define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free #define obstack_chunk_free free
void init_search (); void init_search ();
extern struct obstack *current_obstack; extern struct obstack *current_obstack;
extern tree abort_fndecl;
#include "stack.h" #include "stack.h"
...@@ -2626,6 +2628,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets) ...@@ -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 = FNADDR_FROM_VTABLE_ENTRY (current_fndecl);
current_fndecl = TREE_OPERAND (current_fndecl, 0); current_fndecl = TREE_OPERAND (current_fndecl, 0);
if (current_fndecl if (current_fndecl
&& current_fndecl != abort_fndecl
&& (vc=virtual_context (current_fndecl, t, vbase)) != vbase) && (vc=virtual_context (current_fndecl, t, vbase)) != vbase)
{ {
/* This may in fact need a runtime fixup. */ /* This may in fact need a runtime fixup. */
......
...@@ -153,7 +153,7 @@ lvalue_p (ref) ...@@ -153,7 +153,7 @@ lvalue_p (ref)
return 1; return 1;
case CALL_EXPR: case CALL_EXPR:
if (TREE_ADDRESSABLE (TREE_TYPE (ref))) if (IS_AGGR_TYPE (TREE_TYPE (ref)))
return 1; return 1;
break; break;
...@@ -217,8 +217,12 @@ build_cplus_new (type, init, with_cleanup_p) ...@@ -217,8 +217,12 @@ build_cplus_new (type, init, with_cleanup_p)
tree init; tree init;
int with_cleanup_p; int with_cleanup_p;
{ {
tree slot = build (VAR_DECL, type); tree slot;
tree rval = build (NEW_EXPR, type, 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_OPERAND (init, 0), TREE_OPERAND (init, 1), slot);
TREE_SIDE_EFFECTS (rval) = 1; TREE_SIDE_EFFECTS (rval) = 1;
TREE_ADDRESSABLE (rval) = 1; TREE_ADDRESSABLE (rval) = 1;
......
...@@ -37,6 +37,7 @@ extern void warning (); ...@@ -37,6 +37,7 @@ extern void warning ();
#include "rtl.h" #include "rtl.h"
#include "cp-tree.h" #include "cp-tree.h"
#include "flags.h" #include "flags.h"
#include "output.h"
int mark_addressable (); int mark_addressable ();
static tree convert_for_assignment (); static tree convert_for_assignment ();
...@@ -2665,8 +2666,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) ...@@ -2665,8 +2666,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
/* Convert `float' to `double'. */ /* Convert `float' to `double'. */
result = tree_cons (NULL_TREE, convert (double_type_node, val), result); result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
else if (TYPE_LANG_SPECIFIC (TREE_TYPE (val)) else if (TYPE_LANG_SPECIFIC (TREE_TYPE (val))
&& (! TYPE_HAS_INIT_REF (TREE_TYPE (val)) && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val)))
|| TYPE_HAS_COMPLEX_INIT_REF (TREE_TYPE (val))))
{ {
cp_warning ("cannot pass objects of type `%T' through `...'", cp_warning ("cannot pass objects of type `%T' through `...'",
TREE_TYPE (val)); TREE_TYPE (val));
...@@ -5454,6 +5454,26 @@ init_noncopied_parts (lhs, list) ...@@ -5454,6 +5454,26 @@ init_noncopied_parts (lhs, list)
return parts; 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. /* Build an assignment expression of lvalue LHS from value RHS.
MODIFYCODE is the code for a binary operator that we use 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. to combine the old value of LHS with RHS to get the new value.
...@@ -5586,7 +5606,7 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5586,7 +5606,7 @@ build_modify_expr (lhs, modifycode, rhs)
/* Do the default thing */; /* Do the default thing */;
else if (! TYPE_HAS_CONSTRUCTOR (lhstype)) else if (! TYPE_HAS_CONSTRUCTOR (lhstype))
cp_error ("`%T' has no constructors", 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))) && TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
/* Do the default thing */; /* Do the default thing */;
else else
...@@ -5607,8 +5627,7 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5607,8 +5627,7 @@ build_modify_expr (lhs, modifycode, rhs)
/* Do the default thing */; /* Do the default thing */;
else if (! TYPE_HAS_ASSIGNMENT (lhstype)) else if (! TYPE_HAS_ASSIGNMENT (lhstype))
cp_error ("`%T' does not define operator=", lhstype); cp_error ("`%T' does not define operator=", lhstype);
else if (! TYPE_HAS_REAL_ASSIGNMENT (lhstype) else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (lhstype)
&& ! TYPE_HAS_COMPLEX_ASSIGN_REF (lhstype)
&& TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs))) && TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
/* Do the default thing */; /* Do the default thing */;
else else
...@@ -6002,28 +6021,12 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -6002,28 +6021,12 @@ build_modify_expr (lhs, modifycode, rhs)
&& TYPE_NEEDS_CONSTRUCTING (lhstype)) && TYPE_NEEDS_CONSTRUCTING (lhstype))
newrhs = build_cplus_new (lhstype, newrhs, 0); newrhs = build_cplus_new (lhstype, newrhs, 0);
if (TREE_CODE (newrhs) == TARGET_EXPR)
{
/* Can't initialize directly from a TARGET_EXPR, since that would /* Can't initialize directly from a TARGET_EXPR, since that would
cause the lhs to be constructed twice. So we force the cause the lhs to be constructed twice. So we force the
TARGET_EXPR to be expanded. expand_expr should really do this TARGET_EXPR to be expanded. expand_expr should really do this
by itself. */ by itself. */
if (TREE_CODE (newrhs) == TARGET_EXPR)
tree xval = make_node (RTL_EXPR); newrhs = expand_target_expr (newrhs);
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;
}
} }
if (TREE_CODE (newrhs) == ERROR_MARK) if (TREE_CODE (newrhs) == ERROR_MARK)
...@@ -6964,6 +6967,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) ...@@ -6964,6 +6967,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
rhs = build_cplus_new (type, TREE_OPERAND (rhs, 0), 0); rhs = build_cplus_new (type, TREE_OPERAND (rhs, 0), 0);
return rhs; return rhs;
} }
else if (TYPE_HAS_TRIVIAL_INIT_REF (type))
return rhs;
} }
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype) if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)
|| (IS_AGGR_TYPE (rhstype) && UNIQUELY_DERIVED_FROM_P (type, rhstype))) || (IS_AGGR_TYPE (rhstype) && UNIQUELY_DERIVED_FROM_P (type, rhstype)))
...@@ -7227,6 +7232,13 @@ c_expand_return (retval) ...@@ -7227,6 +7232,13 @@ c_expand_return (retval)
(3) If an X(X&) constructor is defined, the return (3) If an X(X&) constructor is defined, the return
value must be returned via that. */ 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 if (retval == result
/* Watch out for constructors, which "return" aggregates /* Watch out for constructors, which "return" aggregates
via initialization, but which otherwise "return" a pointer. */ via initialization, but which otherwise "return" a pointer. */
...@@ -7243,12 +7255,8 @@ c_expand_return (retval) ...@@ -7243,12 +7255,8 @@ c_expand_return (retval)
use_temp = obey_regdecls; 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_aggr_init (result, retval, 0, LOOKUP_ONLYCONVERTING);
expand_cleanups_to (NULL_TREE); expand_cleanups_to (NULL_TREE);
DECL_INITIAL (result) = NULL_TREE; DECL_INITIAL (result) = NULL_TREE;
......
...@@ -540,11 +540,12 @@ store_init_value (decl, init) ...@@ -540,11 +540,12 @@ store_init_value (decl, init)
/* Take care of C++ business up here. */ /* Take care of C++ business up here. */
type = TYPE_MAIN_VARIANT (type); type = TYPE_MAIN_VARIANT (type);
/* implicitly tests if IS_AGGR_TYPE. */ if (IS_AGGR_TYPE (type))
if (TYPE_NEEDS_CONSTRUCTING (type) && TREE_CODE (init) != CONSTRUCTOR)
my_friendly_abort (109);
else 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 /* Although we are not allowed to declare variables of signature
type, we complain about a possible constructor call in such a type, we complain about a possible constructor call in such a
declaration as well. */ declaration as well. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment