67th Cygnus<->FSF merge

From-SVN: r9433
This commit is contained in:
Mike Stump 1995-04-24 17:27:46 +00:00
parent 87c7361897
commit e8abc66f60
18 changed files with 357 additions and 480 deletions

View File

@ -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

View File

@ -27,6 +27,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "cp-tree.h"
#include "class.h"
#include "output.h"
#include "flags.h"
#include "obstack.h"
@ -1683,10 +1684,24 @@ build_method_call (instance, name, parms, basetype_path, flags)
need_vtbl = (dtor_label || ctor_label)
? unneeded : maybe_needed;
instance = C_C_D;
instance_ptr = current_class_decl;
result = build_field_call (TYPE_BINFO (current_class_type),
instance_ptr, name, parms);
/* If `this' is a signature pointer and `name' is not a constructor,
we are calling a signature member function. In that case, set the
`basetype' to the signature type and dereference the `optr' field. */
if (IS_SIGNATURE_POINTER (basetype)
&& TYPE_IDENTIFIER (basetype) != name)
{
basetype = SIGNATURE_TYPE (basetype);
instance_ptr = build_optr_ref (instance);
instance_ptr = convert (TYPE_POINTER_TO (basetype), instance_ptr);
basetype_path = TYPE_BINFO (basetype);
}
else
{
instance = C_C_D;
instance_ptr = current_class_decl;
basetype_path = TYPE_BINFO (current_class_type);
}
result = build_field_call (basetype_path, instance_ptr, name, parms);
if (result)
return result;

View File

@ -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))

View File

@ -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)

View File

@ -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

View File

@ -34,6 +34,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "cp-tree.h"
#include "decl.h"
#include "lex.h"
#include "output.h"
extern tree grokdeclarator ();
extern tree get_file_function_name ();
@ -1948,8 +1949,13 @@ void
cplus_decl_attributes (decl, attributes, prefix_attributes)
tree decl, attributes, prefix_attributes;
{
if (decl && decl != void_type_node)
decl_attributes (decl, attributes, prefix_attributes);
if (decl == NULL_TREE || decl == void_type_node)
return;
if (TREE_CODE (decl) == TEMPLATE_DECL)
decl = DECL_TEMPLATE_RESULT (decl);
decl_attributes (decl, attributes, prefix_attributes);
}
/* CONSTRUCTOR_NAME:
@ -2775,6 +2781,8 @@ import_export_inline (decl)
}
else
TREE_PUBLIC (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;
}
extern int parse_time, varconst_time;
@ -3086,11 +3094,12 @@ finish_file ()
inline'. */
{
int reconsider = 1; /* More may be referenced; check again */
saved_inlines = tree_cons (NULL_TREE, NULL_TREE, saved_inlines);
while (reconsider)
{
tree last = saved_inlines;
tree last = saved_inlines = tree_cons (NULL_TREE, NULL_TREE,
saved_inlines);
tree last_head = last;
tree place = TREE_CHAIN (saved_inlines);
reconsider = 0;
@ -3100,11 +3109,23 @@ finish_file ()
{
tree decl = TREE_VALUE (place);
/* Slice out the empty elements put in just above in the
previous reconsidering. */
if (decl == NULL_TREE)
{
TREE_CHAIN (last) = TREE_CHAIN (place);
continue;
}
if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl))
{
if (TREE_USED (decl)
|| (TREE_PUBLIC (decl) && DECL_NOT_REALLY_EXTERN (decl)))
synthesize_method (decl);
{
synthesize_method (decl);
if (TREE_ASM_WRITTEN (decl))
reconsider = 1;
}
else
{
last = place;

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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. */

View File

@ -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;

View File

@ -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) */

View File

@ -38,6 +38,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "decl.h"
#include "parse.h"
#include "lex.h"
#include "output.h"
extern struct obstack permanent_obstack;
extern tree grokdeclarator ();
@ -2510,11 +2511,17 @@ do_function_instantiation (declspecs, declarator, storage)
tree declspecs, declarator, storage;
{
tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, 0);
tree name = DECL_NAME (decl);
tree fn = IDENTIFIER_GLOBAL_VALUE (name);
tree name;
tree fn;
tree result = NULL_TREE;
int extern_p = 0;
if (fn)
/* If we've already seen this template instance, use it. */
if (name = DECL_ASSEMBLER_NAME (decl),
fn = IDENTIFIER_GLOBAL_VALUE (name),
fn && DECL_TEMPLATE_INSTANTIATION (fn))
result = fn;
else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn)
{
for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
if (decls_match (fn, decl)
@ -2578,12 +2585,14 @@ mark_class_instantiated (t, extern_p)
rest_of_type_compilation (t, 1);
}
}
void
do_type_instantiation (name, storage)
tree name, storage;
{
tree t = TREE_TYPE (name);
int extern_p;
int extern_p = 0;
int nomem_p = 0;
/* With -fexternal-templates, explicit instantiations are treated the same
as implicit ones. */
@ -2598,7 +2607,9 @@ do_type_instantiation (name, storage)
}
if (storage == NULL_TREE)
extern_p = 0;
/* OK */;
else if (storage == ridpointers[(int) RID_INLINE])
nomem_p = 1;
else if (storage == ridpointers[(int) RID_EXTERN])
extern_p = 1;
else
@ -2618,7 +2629,10 @@ do_type_instantiation (name, storage)
mark_class_instantiated (t, extern_p);
repo_template_instantiated (t, extern_p);
}
if (nomem_p)
return;
{
tree tmp;
/* Classes nested in template classes currently don't have an

View File

@ -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:

View File

@ -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. */

View File

@ -153,7 +153,7 @@ lvalue_p (ref)
return 1;
case CALL_EXPR:
if (TREE_ADDRESSABLE (TREE_TYPE (ref)))
if (IS_AGGR_TYPE (TREE_TYPE (ref)))
return 1;
break;
@ -217,9 +217,13 @@ build_cplus_new (type, init, with_cleanup_p)
tree init;
int with_cleanup_p;
{
tree slot = build (VAR_DECL, type);
tree rval = build (NEW_EXPR, type,
TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot);
tree slot;
tree rval;
slot = build (VAR_DECL, type);
layout_decl (slot, 0);
rval = build (NEW_EXPR, type,
TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot);
TREE_SIDE_EFFECTS (rval) = 1;
TREE_ADDRESSABLE (rval) = 1;
rval = build (TARGET_EXPR, type, slot, rval, 0);

View File

@ -37,6 +37,7 @@ extern void warning ();
#include "rtl.h"
#include "cp-tree.h"
#include "flags.h"
#include "output.h"
int mark_addressable ();
static tree convert_for_assignment ();
@ -2665,8 +2666,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
/* Convert `float' to `double'. */
result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
else if (TYPE_LANG_SPECIFIC (TREE_TYPE (val))
&& (! TYPE_HAS_INIT_REF (TREE_TYPE (val))
|| TYPE_HAS_COMPLEX_INIT_REF (TREE_TYPE (val))))
&& ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val)))
{
cp_warning ("cannot pass objects of type `%T' through `...'",
TREE_TYPE (val));
@ -5454,6 +5454,26 @@ init_noncopied_parts (lhs, list)
return parts;
}
tree
expand_target_expr (t)
tree t;
{
tree xval = make_node (RTL_EXPR);
rtx rtxval;
do_pending_stack_adjust ();
start_sequence_for_rtl_expr (xval);
emit_note (0, -1);
rtxval = expand_expr (t, NULL, VOIDmode, 0);
do_pending_stack_adjust ();
TREE_SIDE_EFFECTS (xval) = 1;
RTL_EXPR_SEQUENCE (xval) = get_insns ();
end_sequence ();
RTL_EXPR_RTL (xval) = rtxval;
TREE_TYPE (xval) = TREE_TYPE (t);
return xval;
}
/* Build an assignment expression of lvalue LHS from value RHS.
MODIFYCODE is the code for a binary operator that we use
to combine the old value of LHS with RHS to get the new value.
@ -5586,7 +5606,7 @@ build_modify_expr (lhs, modifycode, rhs)
/* Do the default thing */;
else if (! TYPE_HAS_CONSTRUCTOR (lhstype))
cp_error ("`%T' has no constructors", lhstype);
else if (! TYPE_NEEDS_CONSTRUCTING (lhstype)
else if (TYPE_HAS_TRIVIAL_INIT_REF (lhstype)
&& TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
/* Do the default thing */;
else
@ -5607,8 +5627,7 @@ build_modify_expr (lhs, modifycode, rhs)
/* Do the default thing */;
else if (! TYPE_HAS_ASSIGNMENT (lhstype))
cp_error ("`%T' does not define operator=", lhstype);
else if (! TYPE_HAS_REAL_ASSIGNMENT (lhstype)
&& ! TYPE_HAS_COMPLEX_ASSIGN_REF (lhstype)
else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (lhstype)
&& TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
/* Do the default thing */;
else
@ -6002,28 +6021,12 @@ build_modify_expr (lhs, modifycode, rhs)
&& TYPE_NEEDS_CONSTRUCTING (lhstype))
newrhs = build_cplus_new (lhstype, newrhs, 0);
/* Can't initialize directly from a TARGET_EXPR, since that would
cause the lhs to be constructed twice. So we force the
TARGET_EXPR to be expanded. expand_expr should really do this
by itself. */
if (TREE_CODE (newrhs) == TARGET_EXPR)
{
/* Can't initialize directly from a TARGET_EXPR, since that would
cause the lhs to be constructed twice. So we force the
TARGET_EXPR to be expanded. expand_expr should really do this
by itself. */
tree xval = make_node (RTL_EXPR);
rtx rtxval;
do_pending_stack_adjust ();
start_sequence_for_rtl_expr (xval);
emit_note (0, -1);
rtxval = expand_expr (newrhs, NULL, VOIDmode, 0);
do_pending_stack_adjust ();
TREE_SIDE_EFFECTS (xval) = 1;
RTL_EXPR_SEQUENCE (xval) = get_insns ();
end_sequence ();
RTL_EXPR_RTL (xval) = rtxval;
TREE_TYPE (xval) = lhstype;
newrhs = xval;
}
newrhs = expand_target_expr (newrhs);
}
if (TREE_CODE (newrhs) == ERROR_MARK)
@ -6964,6 +6967,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
rhs = build_cplus_new (type, TREE_OPERAND (rhs, 0), 0);
return rhs;
}
else if (TYPE_HAS_TRIVIAL_INIT_REF (type))
return rhs;
}
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)
|| (IS_AGGR_TYPE (rhstype) && UNIQUELY_DERIVED_FROM_P (type, rhstype)))
@ -7227,6 +7232,13 @@ c_expand_return (retval)
(3) If an X(X&) constructor is defined, the return
value must be returned via that. */
/* If we're returning in a register, we can't initialize the
return value from a TARGET_EXPR. */
if (TREE_CODE (retval) == TARGET_EXPR
&& TYPE_MAIN_VARIANT (TREE_TYPE (retval)) == TYPE_MAIN_VARIANT (valtype)
&& ! current_function_returns_struct)
retval = expand_target_expr (retval);
if (retval == result
/* Watch out for constructors, which "return" aggregates
via initialization, but which otherwise "return" a pointer. */
@ -7243,12 +7255,8 @@ c_expand_return (retval)
use_temp = obey_regdecls;
}
}
else if (IS_AGGR_TYPE (valtype) && TYPE_NEEDS_CONSTRUCTING (valtype))
else if (IS_AGGR_TYPE (valtype) && current_function_returns_struct)
{
/* Throw away the cleanup that `build_functional_cast' gave us. */
if (TREE_CODE (retval) == WITH_CLEANUP_EXPR
&& TREE_CODE (TREE_OPERAND (retval, 0)) == TARGET_EXPR)
retval = TREE_OPERAND (retval, 0);
expand_aggr_init (result, retval, 0, LOOKUP_ONLYCONVERTING);
expand_cleanups_to (NULL_TREE);
DECL_INITIAL (result) = NULL_TREE;

View File

@ -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. */