41st Cygnus<->FSF merge

From-SVN: r7553
This commit is contained in:
Mike Stump 1994-06-24 00:54:38 +00:00
parent f6ba0600ff
commit a32034654e
12 changed files with 255 additions and 296 deletions

View File

@ -1,3 +1,91 @@
Thu Jun 23 00:22:28 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (grokdeclarator): Set explicit_int for decls that just
specify, say, 'long'.
* init.c (do_friend): Do overload C functions (or call pushdecl,
anyaway).
Wed Jun 22 13:40:49 1994 Jason Merrill (jason@deneb.cygnus.com)
* cvt.c (build_up_reference): Don't call readonly_error.
(convert_to_reference): Propagate const and volatile from expr to
its type.
* tree.c (lvalue_p): Random CALL_EXPRs are not lvalues.
* cvt.c (build_up_reference): Break out WITH_CLEANUP_EXPR when
creating a temporary.
(convert_to_reference): Lose excessive and incorrect trickiness.
(cp_convert): Call build_cplus_new with with_cleanup_p set.
* typeck2.c (build_functional_cast): Ditto.
Tue Jun 21 17:38:38 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (grokdeclarator): signed, unsigned, long and short all
imply 'int'.
* decl.c (grokdeclarator): Allow "this is a type" syntax.
(grok_reference_init): Simplify and fix.
Sun Jun 19 17:08:48 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (grokdeclarator): pedwarn about a typedef that specifies no
type.
Sat Jun 18 04:16:50 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (start_function): Move TREE_PUBLIC and DECL_EXTERNAL
tinkering to after call to pushdecl.
Fri Jun 17 14:48:28 1994 Jason Merrill (jason@deneb.cygnus.com)
* call.c (build_method_call): Handle destructors for non-aggregate
types properly.
Thu Jun 16 16:48:05 1994 Jason Merrill (jason@deneb.cygnus.com)
* call.c (build_method_call): Make sure that the name given for the
destructor matches the constructor_name of the instance.
* pt.c (do_function_instantiation): A non-extern instantiation
overrides a later extern one.
(do_type_instantiation): Ditto.
Wed Jun 15 19:34:54 1994 Jason Merrill (jason@deneb.cygnus.com)
* init.c (expand_aggr_init): Use TYPE_MAIN_VARIANT to get the
unqualified array type.
* cp-tree.h (EMPTY_CONSTRUCTOR_P): Tests whether NODE is a
CONSTRUCTOR with no elements.
* decl.c (various): Lose empty_init_node.
(finish_decl): Use EMPTY_CONSTRUCTOR_P, do the empty CONSTRUCTOR
thing depending on the value of DECL_COMMON instead of
flag_conserve_space, do the empty CONSTRUCTOR thing for types that
don't have constructors, don't treat a real empty CONSTRUCTOR
specially.
* typeck2.c (process_init_constructor): Don't treat empty_init_node
specially.
Wed Jun 15 19:05:25 1994 Mike Stump (mrs@cygnus.com)
* class.c (override_one_vtable): Don't forget to merge in an old
overrider when we wanted to reuse a vtable, but couldn't.
Wed Jun 15 15:03:16 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (start_decl): Put statics in common again.
* decl.c (grokdeclarator): Return NULL_TREE for an error rather than
setting the type to error_mark_node.
* typeck.c (build_modify_expr): Build up a COMPOUND_EXPR for enum
bitfield assignments.
Tue Jun 14 12:23:38 1994 Jason Merrill (jason@deneb.cygnus.com) Tue Jun 14 12:23:38 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (grok_op_properties): Const objects can be passed by value. * decl.c (grok_op_properties): Const objects can be passed by value.

View File

@ -1603,14 +1603,22 @@ build_method_call (instance, name, parms, basetype_path, flags)
name = TREE_OPERAND (name, 0); name = TREE_OPERAND (name, 0);
if (parms) if (parms)
error ("destructors take no parameters"); error ("destructors take no parameters");
basetype = get_type_value (name); basetype = TREE_TYPE (instance);
if (basetype == NULL_TREE) if (IS_AGGR_TYPE (basetype))
{ {
cp_error ("call to destructor for non-type `%D'", name); if (name == constructor_name (basetype))
return void_zero_node; goto huzzah;
} }
if (basetype != TREE_TYPE(instance)) else
basetype = TREE_TYPE(instance); {
if (basetype == get_type_value (name))
goto huzzah;
}
cp_error ("destructor name `~%D' does not match type `%T' of expression",
name, basetype);
return void_zero_node;
huzzah:
if (! TYPE_HAS_DESTRUCTOR (basetype)) if (! TYPE_HAS_DESTRUCTOR (basetype))
return void_zero_node; return void_zero_node;
instance = default_conversion (instance); instance = default_conversion (instance);

View File

@ -2400,6 +2400,10 @@ override_one_vtable (binfo, old, t)
} }
TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals); TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals);
} }
else if (choose == NEITHER)
{
TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals);
}
} }
else else
{ {

View File

@ -1167,6 +1167,9 @@ struct lang_decl
has been duly initialized in its constructor. */ has been duly initialized in its constructor. */
#define TREE_HAS_CONSTRUCTOR(NODE) (TREE_LANG_FLAG_4(NODE)) #define TREE_HAS_CONSTRUCTOR(NODE) (TREE_LANG_FLAG_4(NODE))
#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \
&& CONSTRUCTOR_ELTS (NODE) == NULL_TREE)
/* Indicates that a NON_LVALUE_EXPR came from a C++ reference. /* Indicates that a NON_LVALUE_EXPR came from a C++ reference.
Used to generate more helpful error message in case somebody Used to generate more helpful error message in case somebody
tries to take its address. */ tries to take its address. */

View File

@ -337,7 +337,20 @@ build_up_reference (type, arg, flags, checkconst)
TREE_READONLY (arg) = 0; TREE_READONLY (arg) = 0;
} }
#if 0
if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
{
rval = copy_node (arg);
TREE_TYPE (rval) = build_pointer_type (TREE_TYPE (TREE_TYPE (arg)));
}
else
rval = arg;
rval = convert (build_pointer_type (TREE_TYPE (type)), rval);
TREE_TYPE (rval) = type;
#else
rval = build1 (CONVERT_EXPR, type, arg); rval = build1 (CONVERT_EXPR, type, arg);
#endif
TREE_REFERENCE_EXPR (rval) = 1; TREE_REFERENCE_EXPR (rval) = 1;
/* propagate the const flag on something like: /* propagate the const flag on something like:
@ -372,7 +385,7 @@ build_up_reference (type, arg, flags, checkconst)
} }
literal_flag = TREE_CONSTANT (arg); literal_flag = TREE_CONSTANT (arg);
goto done_but_maybe_warn; goto done;
/* Get this out of a register if we happened to be in one by accident. /* Get this out of a register if we happened to be in one by accident.
Also, build up references to non-lvalues it we must. */ Also, build up references to non-lvalues it we must. */
@ -409,7 +422,7 @@ build_up_reference (type, arg, flags, checkconst)
TREE_TYPE (rval) = type; TREE_TYPE (rval) = type;
literal_flag = staticp (TREE_OPERAND (targ, 0)); literal_flag = staticp (TREE_OPERAND (targ, 0));
goto done_but_maybe_warn; goto done;
/* Anything not already handled and not a true memory reference /* Anything not already handled and not a true memory reference
needs to have a reference built up. Do so silently for needs to have a reference built up. Do so silently for
@ -537,7 +550,12 @@ build_up_reference (type, arg, flags, checkconst)
if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype)) if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype))
{ {
temp = build_cplus_new (argtype, targ, 1); temp = build_cplus_new (argtype, targ, 1);
rval = build1 (ADDR_EXPR, type, temp); if (TREE_CODE (temp) == WITH_CLEANUP_EXPR)
rval = build (WITH_CLEANUP_EXPR, type,
build1 (ADDR_EXPR, type, TREE_OPERAND (temp, 0)),
0, TREE_OPERAND (temp, 2));
else
rval = build1 (ADDR_EXPR, type, temp);
goto done; goto done;
} }
else else
@ -572,10 +590,6 @@ build_up_reference (type, arg, flags, checkconst)
else else
rval = build1 (ADDR_EXPR, type, arg); rval = build1 (ADDR_EXPR, type, arg);
done_but_maybe_warn:
if (checkconst && TREE_READONLY (arg) && ! TYPE_READONLY (target_type))
readonly_error (arg, "conversion to reference", 1);
done: done:
if (TYPE_USES_COMPLEX_INHERITANCE (argtype)) if (TYPE_USES_COMPLEX_INHERITANCE (argtype))
{ {
@ -636,7 +650,11 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
if (form == REFERENCE_TYPE) if (form == REFERENCE_TYPE)
ttr = TREE_TYPE (TREE_TYPE (expr)); ttr = TREE_TYPE (TREE_TYPE (expr));
else else
ttr = TREE_TYPE (expr); {
int r = TREE_READONLY (expr);
int v = TREE_THIS_VOLATILE (expr);
ttr = c_build_type_variant (TREE_TYPE (expr), r, v);
}
if (! lvalue_p (expr) && if (! lvalue_p (expr) &&
(decl == NULL_TREE || ! TYPE_READONLY (ttl))) (decl == NULL_TREE || ! TYPE_READONLY (ttl)))
@ -653,46 +671,20 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
{ {
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr)) if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
cp_pedwarn ("conversion from `%T' to `%T' discards const", cp_pedwarn ("conversion from `%T' to `%T' discards const",
TREE_TYPE (expr), reftype); ttr, reftype);
else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr)) else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
cp_pedwarn ("conversion from `%T' to `%T' discards volatile", cp_pedwarn ("conversion from `%T' to `%T' discards volatile",
TREE_TYPE (expr), reftype); ttr, reftype);
} }
} }
/* If EXPR is of aggregate type, and is really a CALL_EXPR,
then we don't need to convert it to reference type if
it is only being used to initialize DECL which is also
of the same aggregate type. */
if (decl != NULL_TREE && decl != error_mark_node
&& IS_AGGR_TYPE (type)
&& TREE_CODE (expr) == CALL_EXPR
&& TYPE_MAIN_VARIANT (type) == intype)
{
tree e1 = build (INIT_EXPR, void_type_node, decl, expr);
tree e2;
TREE_SIDE_EFFECTS (e1) = 1; if (form == REFERENCE_TYPE)
if (form == REFERENCE_TYPE)
e2 = build1 (NOP_EXPR, reftype, decl);
else
{
e2 = build_unary_op (ADDR_EXPR, decl, 0);
TREE_TYPE (e2) = reftype;
TREE_REFERENCE_EXPR (e2) = 1;
}
return build_compound_expr
(tree_cons (NULL_TREE, e1, build_tree_list (NULL_TREE, e2)));
}
else if (form == REFERENCE_TYPE)
{ {
rval = build1 (NOP_EXPR, rval = copy_node (expr);
build_pointer_type (TREE_TYPE (TREE_TYPE (expr))), TREE_TYPE (rval) = build_pointer_type (TREE_TYPE (TREE_TYPE (expr)));
expr);
rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), rval, rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), rval,
convtype, flags); convtype, flags);
rval = build1 (NOP_EXPR, reftype, rval); TREE_TYPE (rval) = reftype;
return rval; return rval;
} }
@ -1364,7 +1356,7 @@ cp_convert (type, expr, convtype, flags)
return error_mark_node; return error_mark_node;
} }
/* call to constructor successful. */ /* call to constructor successful. */
rval = build_cplus_new (type, rval, 0); rval = build_cplus_new (type, rval, 1);
return rval; return rval;
} }
} }
@ -1415,7 +1407,7 @@ cp_convert (type, expr, convtype, flags)
cp_error ("in conversion to type `%T'", type); cp_error ("in conversion to type `%T'", type);
return error_mark_node; return error_mark_node;
} }
rval = build_cplus_new (type, init, 0); rval = build_cplus_new (type, init, 1);
return rval; return rval;
} }
} }

View File

@ -244,15 +244,6 @@ tree maybe_gc_cleanup;
/* Array type `vtable_entry_type[]' */ /* Array type `vtable_entry_type[]' */
tree vtbl_type_node; tree vtbl_type_node;
/* Static decls which do not have static initializers have no
initializers as far as GNU C is concerned. EMPTY_INIT_NODE
is a static initializer which makes varasm code place the decl
in data rather than in bss space. Such gymnastics are necessary
to avoid the problem that the linker will not include a library
file if all the library appears to contribute are bss variables. */
tree empty_init_node;
/* In a destructor, the point at which all derived class destroying /* In a destructor, the point at which all derived class destroying
has been done, just before any base class destroying will be done. */ has been done, just before any base class destroying will be done. */
@ -4376,7 +4367,6 @@ init_decl_processing ()
TREE_TYPE (integer_two_node) = integer_type_node; TREE_TYPE (integer_two_node) = integer_type_node;
integer_three_node = build_int_2 (3, 0); integer_three_node = build_int_2 (3, 0);
TREE_TYPE (integer_three_node) = integer_type_node; TREE_TYPE (integer_three_node) = integer_type_node;
empty_init_node = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE);
bool_type_node = make_unsigned_type (CHAR_TYPE_SIZE); bool_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
TREE_SET_CODE (bool_type_node, BOOLEAN_TYPE); TREE_SET_CODE (bool_type_node, BOOLEAN_TYPE);
@ -5385,8 +5375,14 @@ start_decl (declarator, declspecs, initialized, raises)
else else
tem = pushdecl (decl); tem = pushdecl (decl);
/* Tell the back-end to use or not use .common as appropriate. */ /* Tell the back-end to use or not use .common as appropriate. If we say
DECL_COMMON (tem) = flag_conserve_space; -fconserve-space, we want this to save space, at the expense of wrong
semantics. If we say -fno-conserve-space, we want this to produce
errors about redefs; to do this we force variables into the data
segment. Common storage is okay for non-public uninitialized data;
the linker can't match it with storage from other files, and we may
save some disk space. */
DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem);
#if 0 #if 0
/* We don't do this yet for GNU C++. */ /* We don't do this yet for GNU C++. */
@ -5556,10 +5552,7 @@ grok_reference_init (decl, type, init, cleanupp)
tree decl, type, init; tree decl, type, init;
tree *cleanupp; tree *cleanupp;
{ {
char *errstr = NULL;
int is_reference;
tree tmp; tree tmp;
tree this_ptr_type, actual_init = NULL_TREE;
if (init == NULL_TREE) if (init == NULL_TREE)
{ {
@ -5585,56 +5578,22 @@ grok_reference_init (decl, type, init, cleanupp)
if (TREE_CODE (init) == TREE_LIST) if (TREE_CODE (init) == TREE_LIST)
init = build_compound_expr (init); init = build_compound_expr (init);
is_reference = TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE;
tmp = is_reference ? convert_from_reference (init) : init;
if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
{ {
/* Note: default conversion is only called in very /* Note: default conversion is only called in very special cases. */
special cases. */
init = default_conversion (init); init = default_conversion (init);
} }
/* Can we just enreference this lvalue? */ tmp = convert_to_reference
if ((is_reference || lvalue_p (init) (type, init, CONV_IMPLICIT, LOOKUP_SPECULATIVELY|LOOKUP_NORMAL, decl);
|| (actual_init = unary_complex_lvalue (ADDR_EXPR, init)))
&& comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
TYPE_MAIN_VARIANT (TREE_TYPE (tmp)), 0))
{
/* This section implements ANSI C++ June 5 1992 WP 8.4.3.5. */
/* A reference to a volatile T cannot be initialized with if (tmp == error_mark_node)
a const T, and vice-versa. */ goto fail;
if (TYPE_VOLATILE (TREE_TYPE (type)) && TREE_READONLY (init)) else if (tmp != NULL_TREE)
errstr = "cannot initialize a reference to a volatile `%T' with a const `%T'";
else if (TYPE_READONLY (TREE_TYPE (type)) && TREE_THIS_VOLATILE (init))
errstr = "cannot initialize a reference to a const `%T' with a volatile `%T'";
/* A reference to a plain T can be initialized only with a plain T. */
else if (!TYPE_VOLATILE (TREE_TYPE (type))
&& !TYPE_READONLY (TREE_TYPE (type)))
{
if (TREE_READONLY (init))
errstr = "cannot initialize a reference to `%T' with a const `%T'";
else if (TREE_THIS_VOLATILE (init))
errstr = "cannot initialize a reference to `%T' with a volatile `%T'";
}
if (errstr)
{
cp_error (errstr, TREE_TYPE (type), TREE_TYPE (tmp));
goto fail;
}
}
/* OK, can we generate a reference then? */
else if ((actual_init = convert_to_reference
(type, init, CONV_IMPLICIT,
LOOKUP_SPECULATIVELY|LOOKUP_NORMAL, decl)))
{ {
if (actual_init == error_mark_node) init = tmp;
goto fail;
init = actual_init;
is_reference = 1;
if (TREE_CODE (init) == WITH_CLEANUP_EXPR) if (TREE_CODE (init) == WITH_CLEANUP_EXPR)
{ {
@ -5643,6 +5602,11 @@ grok_reference_init (decl, type, init, cleanupp)
*cleanupp = TREE_OPERAND (init, 2); *cleanupp = TREE_OPERAND (init, 2);
TREE_OPERAND (init, 2) = error_mark_node; TREE_OPERAND (init, 2) = error_mark_node;
} }
if (TREE_SIDE_EFFECTS (init))
DECL_INITIAL (decl) = save_expr (init);
else
DECL_INITIAL (decl) = init;
} }
else else
{ {
@ -5650,55 +5614,6 @@ grok_reference_init (decl, type, init, cleanupp)
goto fail; goto fail;
} }
/* In the case of initialization, it is permissible
to assign one reference to another. */
this_ptr_type = build_pointer_type (TREE_TYPE (type));
if (is_reference)
{
if (TREE_SIDE_EFFECTS (init))
DECL_INITIAL (decl) = save_expr (init);
else
DECL_INITIAL (decl) = init;
}
else if (lvalue_p (init))
{
tmp = build_unary_op (ADDR_EXPR, init, 0);
if (TREE_CODE (tmp) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (tmp, 0)) == WITH_CLEANUP_EXPR)
{
if (*cleanupp) my_friendly_abort (1);
*cleanupp = TREE_OPERAND (TREE_OPERAND (tmp, 0), 2);
TREE_OPERAND (TREE_OPERAND (tmp, 0), 2) = error_mark_node;
}
if (IS_AGGR_TYPE (TREE_TYPE (this_ptr_type)))
DECL_INITIAL (decl) = convert_pointer_to (TREE_TYPE (this_ptr_type),
tmp);
else
DECL_INITIAL (decl) = convert (this_ptr_type, tmp);
DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
if (DECL_INITIAL (decl) == current_class_decl)
DECL_INITIAL (decl) = copy_node (current_class_decl);
TREE_TYPE (DECL_INITIAL (decl)) = type;
}
/* If actual_init is set here, it is set from the first check above. */
else if (actual_init)
{
/* The initializer for this decl goes into its
DECL_REFERENCE_SLOT. Make sure that we can handle
multiple evaluations without ill effect. */
if (TREE_CODE (actual_init) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (actual_init, 0)) == TARGET_EXPR)
actual_init = save_expr (actual_init);
DECL_INITIAL (decl) = convert_pointer_to (TREE_TYPE (this_ptr_type),
actual_init);
DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
TREE_TYPE (DECL_INITIAL (decl)) = type;
}
else
my_friendly_abort (1);
/* ?? Can this be optimized in some cases to /* ?? Can this be optimized in some cases to
hand back the DECL_INITIAL slot?? */ hand back the DECL_INITIAL slot?? */
if (TYPE_SIZE (TREE_TYPE (type))) if (TYPE_SIZE (TREE_TYPE (type)))
@ -5892,8 +5807,7 @@ finish_decl (decl, init, asmspec_tree, need_pop)
{ {
if (TREE_CODE (type) == ARRAY_TYPE) if (TREE_CODE (type) == ARRAY_TYPE)
init = digest_init (type, init, (tree *) 0); init = digest_init (type, init, (tree *) 0);
else if (TREE_CODE (init) == CONSTRUCTOR else if (TREE_CODE (init) == CONSTRUCTOR)
&& CONSTRUCTOR_ELTS (init) != NULL_TREE)
{ {
if (TYPE_NEEDS_CONSTRUCTING (type)) if (TYPE_NEEDS_CONSTRUCTING (type))
{ {
@ -5951,16 +5865,11 @@ finish_decl (decl, init, asmspec_tree, need_pop)
if (current_binding_level == global_binding_level) if (current_binding_level == global_binding_level)
{ {
tree value; tree value;
if (flag_conserve_space) if (DECL_COMMON (decl))
/* If we say -fconserve-space, we want this to save
space, at the expense of wrong semantics. */
/* Should this be a NULL_TREE? */ /* Should this be a NULL_TREE? */
value = error_mark_node; value = error_mark_node;
else else
/* If we say -fno-conserve-space, we want this to value = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
produce errors about redefs, to do this we make it
go in the data space */
value = digest_init (type, empty_init_node, (tree *) 0);
DECL_INITIAL (decl) = value; DECL_INITIAL (decl) = value;
} }
else else
@ -5972,10 +5881,17 @@ finish_decl (decl, init, asmspec_tree, need_pop)
if (TREE_CODE (init) != TREE_VEC) if (TREE_CODE (init) != TREE_VEC)
init = store_init_value (decl, init); init = store_init_value (decl, init);
/* Don't let anyone try to initialize this variable
until we are ready to do so. */
if (init) if (init)
/* Don't let anyone try to initialize this variable {
until we are ready to do so. */ tree value;
DECL_INITIAL (decl) = error_mark_node; if (DECL_COMMON (decl))
value = error_mark_node;
else
value = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
DECL_INITIAL (decl) = value;
}
} }
} }
else if (DECL_EXTERNAL (decl)) else if (DECL_EXTERNAL (decl))
@ -6002,27 +5918,19 @@ finish_decl (decl, init, asmspec_tree, need_pop)
cp_error ("uninitialized const `%D'", decl); cp_error ("uninitialized const `%D'", decl);
/* Initialize variables in need of static initialization with /* Initialize variables in need of static initialization with
`empty_init_node' to keep assemble_variable from putting them in an empty CONSTRUCTOR to keep assemble_variable from putting them in
the wrong program space. Common storage is okay for non-public the wrong program space. */
uninitialized data; the linker can't match it with storage from
other files, and we may save some disk space. Consts have to go
into data, though, since the backend would put them in text
otherwise. */
if (flag_pic == 0 if (flag_pic == 0
&& TREE_STATIC (decl) && TREE_STATIC (decl)
&& (TREE_PUBLIC (decl) || was_readonly) && TREE_PUBLIC (decl)
&& ! DECL_EXTERNAL (decl) && ! DECL_EXTERNAL (decl)
&& TREE_CODE (decl) == VAR_DECL && TREE_CODE (decl) == VAR_DECL
&& TYPE_NEEDS_CONSTRUCTING (type) && TYPE_NEEDS_CONSTRUCTING (type)
&& (DECL_INITIAL (decl) == NULL_TREE && (DECL_INITIAL (decl) == NULL_TREE
|| DECL_INITIAL (decl) == error_mark_node) || DECL_INITIAL (decl) == error_mark_node)
/* If we say -fconserve-space, we want this to save space, && ! DECL_COMMON (decl))
at the expense of wrong semantics. */ DECL_INITIAL (decl) = build (CONSTRUCTOR, type, NULL_TREE,
&& ! flag_conserve_space) NULL_TREE);
{
tree value = digest_init (type, empty_init_node, (tree *) 0);
DECL_INITIAL (decl) = value;
}
} }
else if (TREE_CODE (decl) == VAR_DECL else if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (type) != REFERENCE_TYPE && TREE_CODE (type) != REFERENCE_TYPE
@ -6182,7 +6090,7 @@ finish_decl (decl, init, asmspec_tree, need_pop)
&& TREE_READONLY (decl) && TREE_READONLY (decl)
&& DECL_INITIAL (decl) != NULL_TREE && DECL_INITIAL (decl) != NULL_TREE
&& DECL_INITIAL (decl) != error_mark_node && DECL_INITIAL (decl) != error_mark_node
&& DECL_INITIAL (decl) != empty_init_node) && ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
{ {
DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl)); DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
@ -6889,9 +6797,8 @@ grokvardecl (type, declarator, specbits, initialized)
if (initialized && DECL_INITIAL (decl) if (initialized && DECL_INITIAL (decl)
/* Complain about multiply-initialized /* Complain about multiply-initialized
member variables, but don't be faked member variables, but don't be faked
out if initializer is faked up from `empty_init_node'. */ out if initializer is empty. */
&& (TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR && ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
|| CONSTRUCTOR_ELTS (DECL_INITIAL (decl)) != NULL_TREE))
error_with_aggr_type (DECL_CONTEXT (decl), error_with_aggr_type (DECL_CONTEXT (decl),
"multiple initializations of static member `%s::%s'", "multiple initializations of static member `%s::%s'",
IDENTIFIER_POINTER (DECL_NAME (decl))); IDENTIFIER_POINTER (DECL_NAME (decl)));
@ -7358,44 +7265,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (TREE_CODE (id) == IDENTIFIER_NODE) if (TREE_CODE (id) == IDENTIFIER_NODE)
{ {
if (id == ridpointers[(int) RID_INT]) if (id == ridpointers[(int) RID_INT]
|| id == ridpointers[(int) RID_CHAR]
|| id == ridpointers[(int) RID_BOOL]
|| id == ridpointers[(int) RID_WCHAR])
{ {
if (type) if (type)
error ("extraneous `int' ignored"); error ("extraneous `%T' ignored", id);
else
{
explicit_int = 1;
type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
}
goto found;
}
if (id == ridpointers[(int) RID_CHAR])
{
if (type)
error ("extraneous `char' ignored");
else
{
explicit_char = 1;
type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
}
goto found;
}
if (id == ridpointers[(int) RID_BOOL])
{
if (type)
error ("extraneous `bool' ignored");
else
{
type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
}
goto found;
}
if (id == ridpointers[(int) RID_WCHAR])
{
if (type)
error ("extraneous `__wchar_t' ignored");
else else
{ {
if (id == ridpointers[(int) RID_INT])
explicit_int = 1;
else if (id == ridpointers[(int) RID_CHAR])
explicit_char = 1;
type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id)); type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
} }
goto found; goto found;
@ -7459,6 +7341,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
which case the type defaults to `unknown type' and is which case the type defaults to `unknown type' and is
instantiated when assigning to a signature pointer or ref. */ instantiated when assigning to a signature pointer or ref. */
if (type == NULL_TREE
&& (RIDBIT_SETP (RID_SIGNED, specbits)
|| RIDBIT_SETP (RID_UNSIGNED, specbits)
|| RIDBIT_SETP (RID_LONG, specbits)
|| RIDBIT_SETP (RID_SHORT, specbits)))
{
/* These imply 'int'. */
type = integer_type_node;
explicit_int = 1;
}
if (type == NULL_TREE) if (type == NULL_TREE)
{ {
explicit_int = -1; explicit_int = -1;
@ -7478,22 +7371,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
opaque_typedef = 1; opaque_typedef = 1;
type = copy_node (opaque_type_node); type = copy_node (opaque_type_node);
} }
/* access declaration */
else if (decl_context == FIELD && declarator
&& TREE_CODE (declarator) == SCOPE_REF)
type = void_type_node;
else else
{ {
if (funcdef_flag) if (funcdef_flag)
{ {
if (warn_return_type if (warn_return_type
&& return_type == return_normal && return_type == return_normal)
&& ! (RIDBIT_SETP (RID_SIGNED, specbits)
|| RIDBIT_SETP (RID_UNSIGNED, specbits)
|| RIDBIT_SETP (RID_LONG, specbits)
|| RIDBIT_SETP (RID_SHORT, specbits)))
/* Save warning until we know what is really going on. */ /* Save warning until we know what is really going on. */
warn_about_return_type = 1; warn_about_return_type = 1;
} }
else if (decl_context == FIELD && declarator else if (RIDBIT_SETP (RID_TYPEDEF, specbits))
&& TREE_CODE (declarator) == SCOPE_REF) pedwarn ("ANSI C++ forbids typedef which does not specify a type");
/* OK -- access declaration */;
else if (declspecs == NULL_TREE && else if (declspecs == NULL_TREE &&
(innermost_code != CALL_EXPR || pedantic)) (innermost_code != CALL_EXPR || pedantic))
cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type or storage class", cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type or storage class",
@ -7522,6 +7414,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
type = ctor_return_type; type = ctor_return_type;
} }
/* Catch typedefs that only specify a type, like 'typedef int;'. */
else if (RIDBIT_SETP (RID_TYPEDEF, specbits) && declarator == NULL_TREE)
{
/* Template "this is a type" syntax; just ignore for now. */
if (processing_template_defn)
return void_type_node;
}
ctype = NULL_TREE; ctype = NULL_TREE;
@ -8481,16 +8380,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
TREE_TYPE (type), TYPE_ARG_TYPES (type)); TREE_TYPE (type), TYPE_ARG_TYPES (type));
else else
{ {
error ("cannot declare member function `%s::%s' within this class", cp_error ("cannot declare member function `%T::%D' within `%T'",
TYPE_NAME_STRING (ctype), name); ctype, name, current_class_type);
return void_type_node; return void_type_node;
} }
} }
else if (TYPE_MAIN_VARIANT (ctype) == current_class_type) else if (TYPE_MAIN_VARIANT (ctype) == current_class_type)
{ {
if (extra_warnings) if (extra_warnings)
warning ("extra qualification `%s' on member `%s' ignored", cp_warning ("redundant qualification `%T' on member `%D' ignored",
TYPE_NAME_STRING (ctype), name); ctype, name);
type = build_offset_type (ctype, type); type = build_offset_type (ctype, type);
} }
else if (TYPE_SIZE (ctype) != NULL_TREE else if (TYPE_SIZE (ctype) != NULL_TREE
@ -8659,7 +8558,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (TREE_CODE (type) == OFFSET_TYPE || TREE_CODE (type) == METHOD_TYPE) if (TREE_CODE (type) == OFFSET_TYPE || TREE_CODE (type) == METHOD_TYPE)
{ {
cp_error_at ("typedef name may not be class-qualified", decl); cp_error_at ("typedef name may not be class-qualified", decl);
TREE_TYPE (decl) = error_mark_node; return NULL_TREE;
} }
else if (quals) else if (quals)
{ {
@ -10773,6 +10672,19 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
(This does not mean `static' in the C sense!) */ (This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1; TREE_STATIC (decl1) = 1;
/* Record the decl so that the function name is defined.
If we already have a decl for this name, and it is a FUNCTION_DECL,
use the old decl. */
if (pre_parsed_p == 0)
{
current_function_decl = decl1 = pushdecl (decl1);
DECL_MAIN_VARIANT (decl1) = decl1;
fntype = TREE_TYPE (decl1);
}
else
current_function_decl = decl1;
/* If this function belongs to an interface, it is public. /* If this function belongs to an interface, it is public.
If it belongs to someone else's interface, it is also external. If it belongs to someone else's interface, it is also external.
It doesn't matter whether it's inline or not. */ It doesn't matter whether it's inline or not. */
@ -10800,19 +10712,6 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
#endif #endif
} }
/* Record the decl so that the function name is defined.
If we already have a decl for this name, and it is a FUNCTION_DECL,
use the old decl. */
if (pre_parsed_p == 0)
{
current_function_decl = decl1 = pushdecl (decl1);
DECL_MAIN_VARIANT (decl1) = decl1;
fntype = TREE_TYPE (decl1);
}
else
current_function_decl = decl1;
if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1)) if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1))
{ {
if (TREE_CODE (fntype) == METHOD_TYPE) if (TREE_CODE (fntype) == METHOD_TYPE)

View File

@ -215,7 +215,7 @@ int warn_extern_inline;
#endif #endif
int dollars_in_ident = DOLLARS_IN_IDENTIFIERS; int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
/* Nonzero for -no-strict-prototype switch: do not consider empty /* Nonzero for -fno-strict-prototype switch: do not consider empty
argument prototype to mean function takes no arguments. */ argument prototype to mean function takes no arguments. */
int strict_prototype = 1; int strict_prototype = 1;

View File

@ -1117,13 +1117,7 @@ expand_aggr_init (exp, init, alias_this)
int was_const_elts = TYPE_READONLY (TREE_TYPE (type)); int was_const_elts = TYPE_READONLY (TREE_TYPE (type));
tree itype = init ? TREE_TYPE (init) : NULL_TREE; tree itype = init ? TREE_TYPE (init) : NULL_TREE;
if (was_const_elts) if (was_const_elts)
{ TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
tree atype = build_cplus_array_type (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
TYPE_DOMAIN (type));
if (init && (TREE_TYPE (exp) == TREE_TYPE (init)))
TREE_TYPE (init) = atype;
TREE_TYPE (exp) = atype;
}
if (init && TREE_TYPE (init) == NULL_TREE) if (init && TREE_TYPE (init) == NULL_TREE)
{ {
/* Handle bad initializers like: /* Handle bad initializers like:
@ -2613,40 +2607,9 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals)
enum overload_flags flags; enum overload_flags flags;
tree quals; tree quals;
{ {
/* first, lets find out if what we are making a friend needs overloading */
tree previous_decl;
int was_c_linkage = 0;
/* Every decl that gets here is a friend of something. */ /* Every decl that gets here is a friend of something. */
DECL_FRIEND_P (decl) = 1; DECL_FRIEND_P (decl) = 1;
/* If we find something in scope, let see if it has extern "C" linkage. */
/* This code is pretty general and should be ripped out and reused
as a separate function. */
if (DECL_NAME (decl))
{
previous_decl = lookup_name (DECL_NAME (decl), 0);
if (previous_decl && TREE_CODE (previous_decl) == TREE_LIST)
{
do
{
if (TREE_TYPE (TREE_VALUE (previous_decl)) == TREE_TYPE (decl))
{
previous_decl = TREE_VALUE (previous_decl);
break;
}
previous_decl = TREE_CHAIN (previous_decl);
}
while (previous_decl);
}
/* It had extern "C" linkage, so don't overload this. */
if (previous_decl && TREE_CODE (previous_decl) == FUNCTION_DECL
&& TREE_TYPE (decl) == TREE_TYPE (previous_decl)
&& DECL_LANGUAGE (previous_decl) == lang_c)
was_c_linkage = 1;
}
if (ctype) if (ctype)
{ {
tree cname = TYPE_NAME (ctype); tree cname = TYPE_NAME (ctype);
@ -2711,7 +2674,6 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals)
decl = void_type_node; decl = void_type_node;
} }
} }
/* never overload C functions */
else if (TREE_CODE (decl) == FUNCTION_DECL else if (TREE_CODE (decl) == FUNCTION_DECL
&& ((IDENTIFIER_LENGTH (declarator) == 4 && ((IDENTIFIER_LENGTH (declarator) == 4
&& IDENTIFIER_POINTER (declarator)[0] == 'm' && IDENTIFIER_POINTER (declarator)[0] == 'm'
@ -2720,8 +2682,7 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals)
&& IDENTIFIER_POINTER (declarator)[0] == '_' && IDENTIFIER_POINTER (declarator)[0] == '_'
&& IDENTIFIER_POINTER (declarator)[1] == '_' && IDENTIFIER_POINTER (declarator)[1] == '_'
&& strncmp (IDENTIFIER_POINTER (declarator)+2, && strncmp (IDENTIFIER_POINTER (declarator)+2,
"builtin_", 8) == 0) "builtin_", 8) == 0)))
|| was_c_linkage))
{ {
/* raw "main", and builtin functions never gets overloaded, /* raw "main", and builtin functions never gets overloaded,
but they can become friends. */ but they can become friends. */

View File

@ -2377,6 +2377,9 @@ do_function_instantiation (declspecs, declarator, storage)
if (flag_external_templates) if (flag_external_templates)
return; return;
if (DECL_EXPLICIT_INSTANTIATION (result) && ! DECL_EXTERNAL (result))
return;
SET_DECL_EXPLICIT_INSTANTIATION (result); SET_DECL_EXPLICIT_INSTANTIATION (result);
TREE_PUBLIC (result) = 1; TREE_PUBLIC (result) = 1;
@ -2399,6 +2402,9 @@ do_type_instantiation (name, storage)
if (flag_external_templates) if (flag_external_templates)
return; return;
if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && ! CLASSTYPE_INTERFACE_ONLY (t))
return;
if (TYPE_SIZE (t) == NULL_TREE) if (TYPE_SIZE (t) == NULL_TREE)
{ {
cp_error ("explicit instantiation of `%#T' before definition of template", cp_error ("explicit instantiation of `%#T' before definition of template",

View File

@ -74,12 +74,6 @@ lvalue_p (ref)
case WITH_CLEANUP_EXPR: case WITH_CLEANUP_EXPR:
return 1; return 1;
case CALL_EXPR:
/* unary_complex_lvalue knows how to deal with this case. */
if (TREE_ADDRESSABLE (TREE_TYPE (ref)))
return 1;
break;
/* A currently unresolved scope ref. */ /* A currently unresolved scope ref. */
case SCOPE_REF: case SCOPE_REF:
my_friendly_abort (103); my_friendly_abort (103);

View File

@ -5336,6 +5336,7 @@ build_modify_expr (lhs, modifycode, rhs)
tree newrhs = rhs; tree newrhs = rhs;
tree lhstype = TREE_TYPE (lhs); tree lhstype = TREE_TYPE (lhs);
tree olhstype = lhstype; tree olhstype = lhstype;
tree olhs = lhs;
/* Types that aren't fully specified cannot be used in assignments. */ /* Types that aren't fully specified cannot be used in assignments. */
lhs = require_complete_type (lhs); lhs = require_complete_type (lhs);
@ -5933,7 +5934,11 @@ build_modify_expr (lhs, modifycode, rhs)
for enum bit fields. */ for enum bit fields. */
if (TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE if (TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE
&& TREE_CODE (olhstype) == ENUMERAL_TYPE) && TREE_CODE (olhstype) == ENUMERAL_TYPE)
return convert_force (olhstype, result); {
result = build (COMPOUND_EXPR, olhstype, result, olhs);
TREE_NO_UNUSED_WARNING (result) = 1;
return result;
}
return convert_for_assignment (olhstype, result, "assignment", return convert_for_assignment (olhstype, result, "assignment",
NULL_TREE, 0); NULL_TREE, 0);
} }

View File

@ -844,7 +844,6 @@ static tree
process_init_constructor (type, init, elts) process_init_constructor (type, init, elts)
tree type, init, *elts; tree type, init, *elts;
{ {
extern tree empty_init_node;
register tree tail; register tree tail;
/* List of the elements of the result constructor, /* List of the elements of the result constructor,
in reverse order. */ in reverse order. */
@ -917,7 +916,7 @@ process_init_constructor (type, init, elts)
members = tree_cons (NULL_TREE, next1, members); members = tree_cons (NULL_TREE, next1, members);
} }
} }
if (TREE_CODE (type) == RECORD_TYPE && init != empty_init_node) if (TREE_CODE (type) == RECORD_TYPE)
{ {
register tree field; register tree field;
@ -1010,7 +1009,7 @@ process_init_constructor (type, init, elts)
} }
} }
if (TREE_CODE (type) == UNION_TYPE && init != empty_init_node) if (TREE_CODE (type) == UNION_TYPE)
{ {
register tree field = TYPE_FIELDS (type); register tree field = TYPE_FIELDS (type);
register tree next1; register tree next1;
@ -1438,7 +1437,7 @@ build_functional_cast (exp, parms)
return error_mark_node; return error_mark_node;
if (current_function_decl) if (current_function_decl)
return build_cplus_new (type, expr_as_ctor, 0); return build_cplus_new (type, expr_as_ctor, 1);
{ {
register tree parm = TREE_OPERAND (expr_as_ctor, 1); register tree parm = TREE_OPERAND (expr_as_ctor, 1);