67th Cygnus<->FSF merge
From-SVN: r9433
This commit is contained in:
parent
87c7361897
commit
e8abc66f60
@ -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
|
||||
|
@ -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;
|
||||
|
||||
/* 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;
|
||||
result = build_field_call (TYPE_BINFO (current_class_type),
|
||||
instance_ptr, name, parms);
|
||||
basetype_path = TYPE_BINFO (current_class_type);
|
||||
}
|
||||
result = build_field_call (basetype_path, instance_ptr, name, parms);
|
||||
|
||||
if (result)
|
||||
return result;
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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,7 +1949,12 @@ void
|
||||
cplus_decl_attributes (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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
if (TREE_ASM_WRITTEN (decl))
|
||||
reconsider = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
last = place;
|
||||
|
@ -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);
|
||||
|
@ -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...
|
||||
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.
|
||||
|
||||
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.
|
||||
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
|
||||
|
||||
|
@ -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);
|
||||
|
350
gcc/cp/lex.c
350
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. */
|
||||
|
@ -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;
|
||||
|
@ -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) */
|
||||
|
24
gcc/cp/pt.c
24
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
|
||||
@ -2619,6 +2630,9 @@ do_type_instantiation (name, storage)
|
||||
repo_template_instantiated (t, extern_p);
|
||||
}
|
||||
|
||||
if (nomem_p)
|
||||
return;
|
||||
|
||||
{
|
||||
tree tmp;
|
||||
/* 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. */
|
||||
|
||||
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:
|
||||
|
@ -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. */
|
||||
|
@ -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,8 +217,12 @@ 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 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;
|
||||
|
@ -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);
|
||||
|
||||
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;
|
||||
}
|
||||
if (TREE_CODE (newrhs) == TARGET_EXPR)
|
||||
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;
|
||||
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user