Commit c91a56d2 by Mike Stump

86th Cygnus<->FSF merge

From-SVN: r11654
parent dd07092e
Fri Mar 29 09:41:02 1996 Jeffrey A. Law <law@cygnus.com Mon Apr 1 09:03:13 1996 Bob Manson <manson@charmed.cygnus.com>
* class.c (finish_struct_1): Propagate the TYPE_PACKED
flag for the type to the type's fields.
Sat Mar 30 12:14:33 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
* parse.y (complex_parmlist, ELLIPSES): Take out ARM-based warning.
Fri Mar 29 15:51:36 1996 Bob Manson <manson@charmed.cygnus.com>
* class.c (base_info, finish_base_struct): Replace
needs_virtual_dtor with base_has_virtual.
(finish_struct_1): Remove the old code that tried to make default
destructors virtual. Use base_has_virtual when checking if we need
to add a vtable entry for the rtti code.
Fri Mar 29 14:02:36 1996 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (push_template_decl): Complain about template decl with
inappropriate declaration.
Fri Mar 29 12:15:35 1996 Bob Manson <manson@charmed.cygnus.com>
* typeck.c (build_x_unary_op): Remove bogus check for taking
the address of a member function.
Fri Mar 29 11:56:02 1996 Jason Merrill <jason@yorick.cygnus.com>
* parse.y (constructor_declarator): Only push the class if
we are not already in the class.
Fri Mar 29 09:41:02 1996 Jeffrey A. Law <law@cygnus.com>
* method.c (emit_thunk): Remove current_call_is_indirect nonsense. * method.c (emit_thunk): Remove current_call_is_indirect nonsense.
Add additional argument to INIT_CUMULATIVE_ARGS. Add additional argument to INIT_CUMULATIVE_ARGS.
Thu Mar 28 16:41:39 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (shadow_tag): Fix error about anon union with methods.
* parse.y (self_reference): Only generate a self-reference if this
is a non-template class.
(opt.component_decl_list): Only use it if it was generated.
* parse.y (component_decl_1): Use constructor_declarator.
(fn.def2): Ditto.
(notype_component_declarator0): Ditto.
Thu Mar 28 15:11:35 1996 Bob Manson <manson@charmed.cygnus.com>
* typeck.c (build_x_unary_op): Add checks for taking the address
of a TARGET_EXPR or of a member function, and give appropriate
warnings.
Thu Mar 28 14:49:26 1996 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (process_template_parm): Allow template type parms to be
used as types for template const parms.
Wed Mar 27 15:51:19 1996 Mike Stump <mrs@cygnus.com>
* init.c (expand_vec_init): Ensure the eh cleanups are on the
function_obstack.
Wed Mar 27 10:14:30 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (lookup_name_real): Be even more picky about the
ambiguous lookup warning.
(grokdeclarator): Tweak SCOPE_REF constructor declarators here.
* parse.y (constructor_declarator): Rather than here.
* parse.y (constructor_declarator): New nonterminal.
(fn.def1): Use it.
(explicit_instantiation): Ditto.
Tue Mar 26 13:41:33 1996 Jason Merrill <jason@yorick.cygnus.com>
Add implicit declaration of class name at class scope.
* decl.c (lookup_name_real): Restrict pedwarn about ambiguous lookup.
* parse.y (self_reference): New nonterminal.
(opt.component_decl_list): Use it.
(fn.def1): Add nested_name_specifier type_name cases.
* class.c (build_self_reference): New function.
(finish_struct): Handle access_default later, move self-reference
decl to the end.
* pt.c (lookup_template_class): Handle getting a TYPE_DECL.
* cp-tree.h: Adjust.
* pt.c (do_function_instantiation): Separate handling of member
functions and non-member functions properly.
Mon Mar 25 14:23:22 1996 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (process_template_parm): Improve error for 'volatile class K'.
* class.c (finish_struct_1): Check the right slot for destructors.
* decl.c (start_enum): Complain about enum templates.
Mon Mar 25 13:25:31 1996 Mike Stump <mrs@cygnus.com>
* init.c (resolve_offset_ref): Offset pointers to member data by one.
* typeck.c (unary_complex_lvalue): Ditto.
Mon Mar 25 13:30:42 1996 Bob Manson <manson@charmed.cygnus.com>
* typeck.c (c_expand_return): Check for a returned local
array name, similar to the check for an ADDR_EXPR.
Mon Mar 25 13:07:19 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (cp_finish_decl): Don't build cleanups for static
variables here.
Fri Mar 22 17:57:55 1996 Mike Stump <mrs@cygnus.com>
* typeck.c (build_modify_expr): Fix error messages to be more
accurate.
* cp-tree.h (assop_as_string): Parallel to op_as_string, but for
assignment operators.
* error.c (assop_as_string): Ditto. Add support for `%Q' for
assignment operators.
Fri Mar 22 13:48:29 1996 Jason Merrill <jason@yorick.cygnus.com> Fri Mar 22 13:48:29 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokdeclarator): Call bad_specifiers for typedefs. Also
give an error if initialized. Pedwarn about nested type with the
same name as its enclosing class.
* pt.c (tsubst, case TYPE_DECL): Set DECL_CONTEXT. * pt.c (tsubst, case TYPE_DECL): Set DECL_CONTEXT.
* typeck.c (require_complete_type): Be sure to instantiate the * typeck.c (require_complete_type): Be sure to instantiate the
......
...@@ -1384,7 +1384,7 @@ struct base_info ...@@ -1384,7 +1384,7 @@ struct base_info
char cant_synth_copy_ctor; char cant_synth_copy_ctor;
char cant_synth_asn_ref; char cant_synth_asn_ref;
char no_const_asn_ref; char no_const_asn_ref;
char needs_virtual_dtor; char base_has_virtual;
}; };
/* Record information about type T derived from its base classes. /* Record information about type T derived from its base classes.
...@@ -1520,9 +1520,8 @@ finish_base_struct (t, b, t_binfo) ...@@ -1520,9 +1520,8 @@ finish_base_struct (t, b, t_binfo)
if (TYPE_VIRTUAL_P (basetype)) if (TYPE_VIRTUAL_P (basetype))
{ {
/* If there's going to be a destructor needed, make /* Remember that the baseclass has virtual members. */
sure it will be virtual. */ b->base_has_virtual = 1;
b->needs_virtual_dtor = 1;
/* Don't borrow virtuals from virtual baseclasses. */ /* Don't borrow virtuals from virtual baseclasses. */
if (TREE_VIA_VIRTUAL (base_binfo)) if (TREE_VIA_VIRTUAL (base_binfo))
...@@ -2973,7 +2972,7 @@ finish_struct_1 (t, attributes, warn_anon) ...@@ -2973,7 +2972,7 @@ finish_struct_1 (t, attributes, warn_anon)
tree fields = TYPE_FIELDS (t); tree fields = TYPE_FIELDS (t);
tree fn_fields = TYPE_METHODS (t); tree fn_fields = TYPE_METHODS (t);
tree x, last_x, method_vec; tree x, last_x, method_vec;
int needs_virtual_dtor; int base_has_virtual;
int all_virtual; int all_virtual;
int has_virtual; int has_virtual;
int max_has_virtual; int max_has_virtual;
...@@ -3083,7 +3082,7 @@ finish_struct_1 (t, attributes, warn_anon) ...@@ -3083,7 +3082,7 @@ finish_struct_1 (t, attributes, warn_anon)
cant_synth_copy_ctor = base_info.cant_synth_copy_ctor; cant_synth_copy_ctor = base_info.cant_synth_copy_ctor;
cant_synth_asn_ref = base_info.cant_synth_asn_ref; cant_synth_asn_ref = base_info.cant_synth_asn_ref;
no_const_asn_ref = base_info.no_const_asn_ref; no_const_asn_ref = base_info.no_const_asn_ref;
needs_virtual_dtor = base_info.needs_virtual_dtor; base_has_virtual = base_info.base_has_virtual;
n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo)); n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo));
aggregate = 0; aggregate = 0;
} }
...@@ -3100,7 +3099,7 @@ finish_struct_1 (t, attributes, warn_anon) ...@@ -3100,7 +3099,7 @@ finish_struct_1 (t, attributes, warn_anon)
cant_synth_copy_ctor = 0; cant_synth_copy_ctor = 0;
cant_synth_asn_ref = 0; cant_synth_asn_ref = 0;
no_const_asn_ref = 0; no_const_asn_ref = 0;
needs_virtual_dtor = 0; base_has_virtual = 0;
} }
#if 0 #if 0
...@@ -3172,6 +3171,9 @@ finish_struct_1 (t, attributes, warn_anon) ...@@ -3172,6 +3171,9 @@ finish_struct_1 (t, attributes, warn_anon)
{ {
GNU_xref_member (current_class_name, x); GNU_xref_member (current_class_name, x);
if (TREE_CODE (x) == FIELD_DECL)
DECL_PACKED (x) |= TYPE_PACKED (t);
/* Handle access declarations. */ /* Handle access declarations. */
if (TREE_CODE (x) == USING_DECL) if (TREE_CODE (x) == USING_DECL)
{ {
...@@ -3537,7 +3539,7 @@ finish_struct_1 (t, attributes, warn_anon) ...@@ -3537,7 +3539,7 @@ finish_struct_1 (t, attributes, warn_anon)
&& !IS_SIGNATURE (t)) && !IS_SIGNATURE (t))
{ {
/* Here we must cons up a destructor on the fly. */ /* Here we must cons up a destructor on the fly. */
tree dtor = cons_up_default_function (t, name, needs_virtual_dtor != 0); tree dtor = cons_up_default_function (t, name, 0);
check_for_override (dtor, t); check_for_override (dtor, t);
/* If we couldn't make it work, then pretend we didn't need it. */ /* If we couldn't make it work, then pretend we didn't need it. */
...@@ -3550,11 +3552,6 @@ finish_struct_1 (t, attributes, warn_anon) ...@@ -3550,11 +3552,6 @@ finish_struct_1 (t, attributes, warn_anon)
TREE_CHAIN (dtor) = fn_fields; TREE_CHAIN (dtor) = fn_fields;
fn_fields = dtor; fn_fields = dtor;
if (DECL_VINDEX (dtor) == NULL_TREE
&& (needs_virtual_dtor
|| pending_virtuals != NULL_TREE
|| pending_hard_virtuals != NULL_TREE))
DECL_VINDEX (dtor) = error_mark_node;
if (DECL_VINDEX (dtor)) if (DECL_VINDEX (dtor))
pending_virtuals = add_virtual_function (pending_virtuals, pending_virtuals = add_virtual_function (pending_virtuals,
&has_virtual, dtor, t); &has_virtual, dtor, t);
...@@ -3563,7 +3560,7 @@ finish_struct_1 (t, attributes, warn_anon) ...@@ -3563,7 +3560,7 @@ finish_struct_1 (t, attributes, warn_anon)
} }
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t); TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
if (flag_rtti && (max_has_virtual > 0 || needs_virtual_dtor) && if (flag_rtti && (max_has_virtual > 0 || base_has_virtual) &&
has_virtual == 0) has_virtual == 0)
has_virtual = 1; has_virtual = 1;
...@@ -4132,7 +4129,7 @@ finish_struct_1 (t, attributes, warn_anon) ...@@ -4132,7 +4129,7 @@ finish_struct_1 (t, attributes, warn_anon)
TYPE_NONCOPIED_PARTS (t) = build_tree_list (default_conversion (TYPE_BINFO_VTABLE (t)), vfield); TYPE_NONCOPIED_PARTS (t) = build_tree_list (default_conversion (TYPE_BINFO_VTABLE (t)), vfield);
if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t) if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
&& DECL_VINDEX (TREE_VEC_ELT (method_vec, 0)) == NULL_TREE) && DECL_VINDEX (TREE_VEC_ELT (method_vec, 1)) == NULL_TREE)
cp_warning ("`%#T' has virtual functions but non-virtual destructor", cp_warning ("`%#T' has virtual functions but non-virtual destructor",
t); t);
} }
...@@ -4212,6 +4209,7 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) ...@@ -4212,6 +4209,7 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
tree name = TYPE_NAME (t); tree name = TYPE_NAME (t);
tree x, last_x = NULL_TREE; tree x, last_x = NULL_TREE;
tree access; tree access;
tree dummy = NULL_TREE;
if (TREE_CODE (name) == TYPE_DECL) if (TREE_CODE (name) == TYPE_DECL)
{ {
...@@ -4233,24 +4231,32 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) ...@@ -4233,24 +4231,32 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
if (IS_SIGNATURE (t)) if (IS_SIGNATURE (t))
append_signature_fields (list_of_fieldlists); append_signature_fields (list_of_fieldlists);
/* Move our self-reference declaration to the end of the field list so
any real field with the same name takes precedence. */
if (list_of_fieldlists
&& TREE_VALUE (list_of_fieldlists)
&& DECL_ARTIFICIAL (TREE_VALUE (list_of_fieldlists)))
{
dummy = TREE_VALUE (list_of_fieldlists);
list_of_fieldlists = TREE_CHAIN (list_of_fieldlists);
}
if (last_x && list_of_fieldlists) if (last_x && list_of_fieldlists)
TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists); TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
while (list_of_fieldlists)
{
access = TREE_PURPOSE (list_of_fieldlists);
/* For signatures, we made all methods `public' in the parser and /* For signatures, we made all methods `public' in the parser and
reported an error if a access specifier was used. */ reported an error if a access specifier was used. */
if (CLASSTYPE_DECLARED_CLASS (t) == 0) if (access == access_default_node)
{ {
if (list_of_fieldlists if (CLASSTYPE_DECLARED_CLASS (t) == 0)
&& TREE_PURPOSE (list_of_fieldlists) == access_default_node) access = access_public_node;
TREE_PURPOSE (list_of_fieldlists) = access_public_node; else
access = access_private_node;
} }
else if (list_of_fieldlists
&& TREE_PURPOSE (list_of_fieldlists) == access_default_node)
TREE_PURPOSE (list_of_fieldlists) = access_private_node;
while (list_of_fieldlists)
{
access = TREE_PURPOSE (list_of_fieldlists);
for (x = TREE_VALUE (list_of_fieldlists); x; x = TREE_CHAIN (x)) for (x = TREE_VALUE (list_of_fieldlists); x; x = TREE_CHAIN (x))
{ {
...@@ -4298,16 +4304,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) ...@@ -4298,16 +4304,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
continue; continue;
} }
#if 0
/* Handle access declarations. */
if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF)
{
tree n = DECL_NAME (x);
x = build_decl
(USING_DECL, DECL_NAME (TREE_OPERAND (n, 1)), TREE_TYPE (x));
DECL_RESULT (x) = n;
}
#endif
if (TREE_CODE (x) != TYPE_DECL) if (TREE_CODE (x) != TYPE_DECL)
DECL_FIELD_CONTEXT (x) = t; DECL_FIELD_CONTEXT (x) = t;
...@@ -4330,7 +4326,7 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) ...@@ -4330,7 +4326,7 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
/* Now add the tags, if any, to the list of TYPE_DECLs /* Now add the tags, if any, to the list of TYPE_DECLs
defined for this type. */ defined for this type. */
if (CLASSTYPE_TAGS (t)) if (CLASSTYPE_TAGS (t) || dummy)
{ {
x = CLASSTYPE_TAGS (t); x = CLASSTYPE_TAGS (t);
while (x) while (x)
...@@ -4350,6 +4346,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) ...@@ -4350,6 +4346,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
x = TREE_CHAIN (x); x = TREE_CHAIN (x);
last_x = chainon (last_x, tag); last_x = chainon (last_x, tag);
} }
if (dummy)
last_x = chainon (last_x, dummy);
if (fields == NULL_TREE) if (fields == NULL_TREE)
fields = last_x; fields = last_x;
CLASSTYPE_LOCAL_TYPEDECLS (t) = 1; CLASSTYPE_LOCAL_TYPEDECLS (t) = 1;
...@@ -5298,6 +5296,7 @@ print_class_statistics () ...@@ -5298,6 +5296,7 @@ print_class_statistics ()
decls that may be cached in the previous_class_values list. For now, let's decls that may be cached in the previous_class_values list. For now, let's
use the permanent obstack, later we may create a dedicated obstack just use the permanent obstack, later we may create a dedicated obstack just
for this purpose. The effect is undone by pop_obstacks. */ for this purpose. The effect is undone by pop_obstacks. */
void void
maybe_push_cache_obstack () maybe_push_cache_obstack ()
{ {
...@@ -5305,3 +5304,24 @@ maybe_push_cache_obstack () ...@@ -5305,3 +5304,24 @@ maybe_push_cache_obstack ()
if (current_class_depth == 1) if (current_class_depth == 1)
current_obstack = &permanent_obstack; current_obstack = &permanent_obstack;
} }
/* Build a dummy reference to ourselves so Derived::Base (and A::A) works,
according to [class]:
The class-name is also inserted
into the scope of the class itself. For purposes of access checking,
the inserted class name is treated as if it were a public member name. */
tree
build_self_reference ()
{
tree name = constructor_name (current_class_type);
tree value = build_lang_decl (TYPE_DECL, name, current_class_type);
DECL_NONLOCAL (value) = 1;
DECL_CONTEXT (value) = current_class_type;
DECL_CLASS_CONTEXT (value) = current_class_type;
CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1;
DECL_ARTIFICIAL (value) = 1;
pushdecl_class_level (value);
return value;
}
...@@ -1967,6 +1967,7 @@ extern tree instantiate_type PROTO((tree, tree, int)); ...@@ -1967,6 +1967,7 @@ extern tree instantiate_type PROTO((tree, tree, int));
extern void print_class_statistics PROTO((void)); extern void print_class_statistics PROTO((void));
extern void maybe_push_cache_obstack PROTO((void)); extern void maybe_push_cache_obstack PROTO((void));
extern unsigned HOST_WIDE_INT skip_rtti_stuff PROTO((tree *)); extern unsigned HOST_WIDE_INT skip_rtti_stuff PROTO((tree *));
extern tree build_self_reference PROTO((void));
/* in cvt.c */ /* in cvt.c */
extern tree convert_to_reference PROTO((tree, tree, int, int, tree)); extern tree convert_to_reference PROTO((tree, tree, int, int, tree));
...@@ -2254,6 +2255,7 @@ extern char *code_as_string PROTO((enum tree_code, int)); ...@@ -2254,6 +2255,7 @@ extern char *code_as_string PROTO((enum tree_code, int));
extern char *language_as_string PROTO((enum languages, int)); extern char *language_as_string PROTO((enum languages, int));
extern char *parm_as_string PROTO((int, int)); extern char *parm_as_string PROTO((int, int));
extern char *op_as_string PROTO((enum tree_code, int)); extern char *op_as_string PROTO((enum tree_code, int));
extern char *assop_as_string PROTO((enum tree_code, int));
extern char *cv_as_string PROTO((tree, int)); extern char *cv_as_string PROTO((tree, int));
/* in method.c */ /* in method.c */
...@@ -2290,7 +2292,6 @@ extern tree lookup_template_class PROTO((tree, tree, tree)); ...@@ -2290,7 +2292,6 @@ extern tree lookup_template_class PROTO((tree, tree, tree));
extern int uses_template_parms PROTO((tree)); extern int uses_template_parms PROTO((tree));
extern tree instantiate_class_template PROTO((tree)); extern tree instantiate_class_template PROTO((tree));
extern tree instantiate_template PROTO((tree, tree *)); extern tree instantiate_template PROTO((tree, tree *));
extern void overload_template_name PROTO((tree));
extern int type_unification PROTO((tree, tree *, tree, tree, int *, int)); extern int type_unification PROTO((tree, tree *, tree, tree, int *, int));
struct tinst_level *tinst_for_decl PROTO((void)); struct tinst_level *tinst_for_decl PROTO((void));
extern void mark_decl_instantiated PROTO((tree, int)); extern void mark_decl_instantiated PROTO((tree, int));
......
...@@ -4501,12 +4501,18 @@ lookup_name_real (name, prefer_type, nonclass) ...@@ -4501,12 +4501,18 @@ lookup_name_real (name, prefer_type, nonclass)
done: done:
if (val) if (val)
{ {
/* This should only warn about types used in qualified-ids. */
if (from_obj && from_obj != val) if (from_obj && from_obj != val)
{ {
cp_pedwarn ("lookup of `%D' in the scope of `%#T' (`%D')", if (looking_for_typename && TREE_CODE (from_obj) == TYPE_DECL
name, got_object, from_obj); && TREE_CODE (val) == TYPE_DECL
cp_pedwarn (" does not match lookup in the current scope (`%D')", && TREE_TYPE (from_obj) != TREE_TYPE (val))
val); {
cp_pedwarn ("lookup of `%D' in the scope of `%#T' (`%#T')",
name, got_object, TREE_TYPE (from_obj));
cp_pedwarn (" does not match lookup in the current scope (`%#T')",
TREE_TYPE (val));
}
} }
if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template) if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
...@@ -5700,14 +5706,15 @@ shadow_tag (declspecs) ...@@ -5700,14 +5706,15 @@ shadow_tag (declspecs)
{ {
/* ANSI C++ June 5 1992 WP 9.5.3. Anonymous unions may not have /* ANSI C++ June 5 1992 WP 9.5.3. Anonymous unions may not have
function members. */ function members. */
if (TYPE_METHODS (t))
error ("an anonymous union cannot have function members");
if (TYPE_FIELDS (t)) if (TYPE_FIELDS (t))
{ {
tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0, tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
NULL_TREE, NULL_TREE); NULL_TREE, NULL_TREE);
finish_anon_union (decl); finish_anon_union (decl);
} }
else
error ("anonymous union cannot have a function member");
} }
else else
{ {
...@@ -6525,7 +6532,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -6525,7 +6532,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
cp_error ("storage size of `%D' isn't constant", decl); cp_error ("storage size of `%D' isn't constant", decl);
} }
if (!DECL_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type)) if (! DECL_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type)
/* Cleanups for static variables are handled by `finish_file'. */
&& ! TREE_STATIC (decl))
{ {
int yes = suspend_momentary (); int yes = suspend_momentary ();
cleanup = maybe_build_cleanup (decl); cleanup = maybe_build_cleanup (decl);
...@@ -7676,8 +7685,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli ...@@ -7676,8 +7685,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
ctype = cname; ctype = cname;
} }
if (ctype if (ctype && TREE_CODE (TREE_OPERAND (decl, 1)) == TYPE_DECL
&& TREE_OPERAND (decl, 1) == constructor_name_full (ctype)) && ((DECL_NAME (TREE_OPERAND (decl, 1))
== constructor_name_full (ctype))
|| (DECL_NAME (TREE_OPERAND (decl, 1))
== constructor_name (ctype))))
TREE_OPERAND (decl, 1) = constructor_name (ctype); TREE_OPERAND (decl, 1) = constructor_name (ctype);
next = &TREE_OPERAND (decl, 1); next = &TREE_OPERAND (decl, 1);
decl = *next; decl = *next;
...@@ -9030,6 +9042,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli ...@@ -9030,6 +9042,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
if (decl_context == FIELD) if (decl_context == FIELD)
{ {
if (declarator == current_class_name)
cp_pedwarn ("ANSI C++ forbids nested type `%D' with same name as enclosing class",
declarator);
decl = build_lang_decl (TYPE_DECL, declarator, type); decl = build_lang_decl (TYPE_DECL, declarator, type);
if (IS_SIGNATURE (current_class_type) && opaque_typedef) if (IS_SIGNATURE (current_class_type) && opaque_typedef)
SIGNATURE_HAS_OPAQUE_TYPEDECLS (current_class_type) = 1; SIGNATURE_HAS_OPAQUE_TYPEDECLS (current_class_type) = 1;
...@@ -9064,6 +9079,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli ...@@ -9064,6 +9079,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
error ("non-object member `%s' cannot be declared mutable", name); error ("non-object member `%s' cannot be declared mutable", name);
} }
bad_specifiers (decl, "type", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
if (initialized)
error ("typedef declaration includes an initializer");
return decl; return decl;
} }
...@@ -10597,15 +10618,19 @@ start_enum (name) ...@@ -10597,15 +10618,19 @@ start_enum (name)
enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1); enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1);
if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE) if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
cp_error ("multiple definition of enum `%T'", enumtype); cp_error ("multiple definition of `%#T'", enumtype);
else else
{ {
enumtype = make_node (ENUMERAL_TYPE); enumtype = make_node (ENUMERAL_TYPE);
pushtag (name, enumtype, 0); pushtag (name, enumtype, 0);
} }
if (b->pseudo_global)
cp_error ("template declaration of `%#T'", enumtype);
if (current_class_type) if (current_class_type)
TREE_ADDRESSABLE (b->tags) = 1; TREE_ADDRESSABLE (b->tags) = 1;
current_local_enum = NULL_TREE; current_local_enum = NULL_TREE;
/* We copy this value because enumerated type constants /* We copy this value because enumerated type constants
......
...@@ -34,6 +34,7 @@ typedef char* cp_printer (); ...@@ -34,6 +34,7 @@ typedef char* cp_printer ();
#define L language_as_string #define L language_as_string
#define O op_as_string #define O op_as_string
#define P parm_as_string #define P parm_as_string
#define Q assop_as_string
#define T type_as_string #define T type_as_string
#define V cv_as_string #define V cv_as_string
...@@ -46,7 +47,7 @@ cp_printer * cp_printers[256] = ...@@ -46,7 +47,7 @@ cp_printer * cp_printers[256] =
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */
_, A, _, C, D, E, _, _, _, _, _, _, L, _, _, O, /* 0x40 */ _, A, _, C, D, E, _, _, _, _, _, _, L, _, _, O, /* 0x40 */
P, _, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */ P, Q, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */
}; };
...@@ -56,6 +57,7 @@ cp_printer * cp_printers[256] = ...@@ -56,6 +57,7 @@ cp_printer * cp_printers[256] =
#undef L #undef L
#undef O #undef O
#undef P #undef P
#undef Q
#undef T #undef T
#undef V #undef V
#undef _ #undef _
...@@ -1504,6 +1506,20 @@ op_as_string (p, v) ...@@ -1504,6 +1506,20 @@ op_as_string (p, v)
} }
char * char *
assop_as_string (p, v)
enum tree_code p;
int v;
{
static char buf[] = "operator ";
if (p == 0)
return "{unknown}";
strcpy (buf + 9, assignop_tab [p]);
return buf;
}
char *
args_as_string (p, v) args_as_string (p, v)
tree p; tree p;
int v; int v;
......
...@@ -2071,6 +2071,14 @@ resolve_offset_ref (exp) ...@@ -2071,6 +2071,14 @@ resolve_offset_ref (exp)
addr = convert_pointer_to (basetype, addr); addr = convert_pointer_to (basetype, addr);
member = convert (ptrdiff_type_node, member = convert (ptrdiff_type_node,
build_unary_op (ADDR_EXPR, member, 0)); build_unary_op (ADDR_EXPR, member, 0));
/* Pointer to data mebers are offset by one, so that a null
pointer with a real value of 0 is distinguishable from an
offset of the first member of a structure. */
member = build_binary_op (MINUS_EXPR, member,
convert (ptrdiff_type_node, integer_one_node),
0);
return build1 (INDIRECT_REF, type, return build1 (INDIRECT_REF, type,
build (PLUS_EXPR, build_pointer_type (type), build (PLUS_EXPR, build_pointer_type (type),
addr, member)); addr, member));
...@@ -3399,13 +3407,31 @@ expand_vec_init (decl, base, maxindex, init, from_array) ...@@ -3399,13 +3407,31 @@ expand_vec_init (decl, base, maxindex, init, from_array)
use_variable (DECL_RTL (base2)); use_variable (DECL_RTL (base2));
} }
expand_end_loop (); expand_end_loop ();
if (TYPE_NEEDS_DESTRUCTOR (type)) if (TYPE_NEEDS_DESTRUCTOR (type) && flag_handle_exceptions)
end_protect (build_array_eh_cleanup (rval, {
build_binary_op (MINUS_EXPR, /* We have to ensure that this can live to the cleanup
maxindex, expansion time, since we know it is only ever needed
iterator, once, generate code now. */
1), push_obstacks_nochange ();
type)); resume_temporary_allocation ();
{
tree e1, e2 = make_node (RTL_EXPR);
TREE_TYPE (e2) = void_type_node;
RTL_EXPR_RTL (e2) = const0_rtx;
TREE_SIDE_EFFECTS (e2) = 1;
start_sequence_for_rtl_expr (e2);
e1 = build_array_eh_cleanup
(rval,
build_binary_op (MINUS_EXPR, maxindex, iterator, 1),
type);
expand_expr (e1, const0_rtx, VOIDmode, 0);
RTL_EXPR_SEQUENCE (e2) = get_insns ();
end_sequence ();
end_protect (e2);
}
pop_obstacks ();
}
expand_end_cond (); expand_end_cond ();
if (obey_regdecls) if (obey_regdecls)
use_variable (DECL_RTL (iterator)); use_variable (DECL_RTL (iterator));
......
...@@ -210,7 +210,7 @@ empty_parms () ...@@ -210,7 +210,7 @@ empty_parms ()
%type <ttype> structsp opt.component_decl_list component_decl_list %type <ttype> structsp opt.component_decl_list component_decl_list
%type <ttype> component_decl component_decl_1 components notype_components %type <ttype> component_decl component_decl_1 components notype_components
%type <ttype> component_declarator component_declarator0 %type <ttype> component_declarator component_declarator0 self_reference
%type <ttype> notype_component_declarator notype_component_declarator0 %type <ttype> notype_component_declarator notype_component_declarator0
%type <ttype> after_type_component_declarator after_type_component_declarator0 %type <ttype> after_type_component_declarator after_type_component_declarator0
%type <ttype> enumlist enumerator %type <ttype> enumlist enumerator
...@@ -231,7 +231,7 @@ empty_parms () ...@@ -231,7 +231,7 @@ empty_parms ()
%token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL %token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL
%token <ttype> PRE_PARSED_CLASS_DECL %token <ttype> PRE_PARSED_CLASS_DECL
%type <ttype> fn.def1 /* Not really! */ %type <ttype> fn.def1 /* Not really! */
%type <ttype> fn.def2 return_id fn.defpen %type <ttype> fn.def2 return_id fn.defpen constructor_declarator
%type <itype> ctor_initializer_opt %type <itype> ctor_initializer_opt
%type <ttype> named_class_head named_class_head_sans_basetype %type <ttype> named_class_head named_class_head_sans_basetype
%type <ttype> named_complex_class_head_sans_basetype %type <ttype> named_complex_class_head_sans_basetype
...@@ -551,6 +551,51 @@ fndef: ...@@ -551,6 +551,51 @@ fndef:
{} {}
; ;
constructor_declarator:
nested_name_specifier type_name '('
{
$$ = build_parse_node (SCOPE_REF, $1, $2);
if ($1 != current_class_type)
{
push_nested_class ($1, 3);
TREE_COMPLEXITY ($$) = current_class_depth;
}
}
parmlist ')' type_quals
{ $$ = build_parse_node (CALL_EXPR, $<ttype>4, $5, $7); }
| nested_name_specifier type_name LEFT_RIGHT type_quals
{
$$ = build_parse_node (SCOPE_REF, $1, $2);
if ($1 != current_class_type)
{
push_nested_class ($1, 3);
TREE_COMPLEXITY ($$) = current_class_depth;
}
$$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $4);
}
| global_scope nested_name_specifier type_name '('
{
$$ = build_parse_node (SCOPE_REF, $2, $3);
if ($2 != current_class_type)
{
push_nested_class ($2, 3);
TREE_COMPLEXITY ($$) = current_class_depth;
}
}
parmlist ')' type_quals
{ $$ = build_parse_node (CALL_EXPR, $<ttype>5, $6, $8); }
| global_scope nested_name_specifier type_name LEFT_RIGHT type_quals
{
$$ = build_parse_node (SCOPE_REF, $2, $3);
if ($2 != current_class_type)
{
push_nested_class ($2, 3);
TREE_COMPLEXITY ($$) = current_class_depth;
}
$$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $5);
}
;
fn.def1: fn.def1:
typed_declspecs declarator exception_specification_opt typed_declspecs declarator exception_specification_opt
{ tree specs, attrs; { tree specs, attrs;
...@@ -571,6 +616,18 @@ fn.def1: ...@@ -571,6 +616,18 @@ fn.def1:
YYERROR1; YYERROR1;
reinit_parse_for_function (); reinit_parse_for_function ();
$$ = NULL_TREE; } $$ = NULL_TREE; }
| declmods constructor_declarator exception_specification_opt
{ tree specs, attrs;
split_specs_attrs ($1, &specs, &attrs);
if (! start_function (specs, $2, $3, attrs, 0))
YYERROR1;
reinit_parse_for_function ();
$$ = NULL_TREE; }
| constructor_declarator exception_specification_opt
{ if (! start_function (NULL_TREE, $$, $2, NULL_TREE, 0))
YYERROR1;
reinit_parse_for_function ();
$$ = NULL_TREE; }
; ;
/* more C++ complexity. See component_decl for a comment on the /* more C++ complexity. See component_decl for a comment on the
...@@ -578,13 +635,6 @@ fn.def1: ...@@ -578,13 +635,6 @@ fn.def1:
fn.def2: fn.def2:
typed_declspecs '(' parmlist ')' type_quals exception_specification_opt typed_declspecs '(' parmlist ')' type_quals exception_specification_opt
{ tree specs = strip_attrs ($1); { tree specs = strip_attrs ($1);
if (TREE_VALUE (specs) == current_class_type)
{
if (TREE_CHAIN (specs) == NULL_TREE)
specs = get_decl_list (current_class_name);
else
TREE_VALUE (specs) = current_class_name;
}
$$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs), $3, $5); $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs), $3, $5);
$$ = start_method (TREE_CHAIN (specs), $$, $6); $$ = start_method (TREE_CHAIN (specs), $$, $6);
rest_of_mdef: rest_of_mdef:
...@@ -608,6 +658,11 @@ fn.def2: ...@@ -608,6 +658,11 @@ fn.def2:
$$ = start_method (specs, $2, $3); goto rest_of_mdef; } $$ = start_method (specs, $2, $3); goto rest_of_mdef; }
| notype_declarator exception_specification_opt | notype_declarator exception_specification_opt
{ $$ = start_method (NULL_TREE, $$, $2); goto rest_of_mdef; } { $$ = start_method (NULL_TREE, $$, $2); goto rest_of_mdef; }
| declmods constructor_declarator exception_specification_opt
{ tree specs = strip_attrs ($1);
$$ = start_method (specs, $2, $3); goto rest_of_mdef; }
| constructor_declarator exception_specification_opt
{ $$ = start_method (NULL_TREE, $$, $2); goto rest_of_mdef; }
; ;
return_id: RETURN IDENTIFIER return_id: RETURN IDENTIFIER
...@@ -726,6 +781,8 @@ explicit_instantiation: ...@@ -726,6 +781,8 @@ explicit_instantiation:
do_function_instantiation (specs, $3, NULL_TREE); } do_function_instantiation (specs, $3, NULL_TREE); }
| TEMPLATE notype_declarator | TEMPLATE notype_declarator
{ do_function_instantiation (NULL_TREE, $2, NULL_TREE); } { do_function_instantiation (NULL_TREE, $2, NULL_TREE); }
| TEMPLATE constructor_declarator
{ do_function_instantiation (NULL_TREE, $2, NULL_TREE); }
| SCSPEC TEMPLATE aggr template_type | SCSPEC TEMPLATE aggr template_type
{ do_type_instantiation ($4, $1); } { do_type_instantiation ($4, $1); }
| SCSPEC TEMPLATE typed_declspecs declarator | SCSPEC TEMPLATE typed_declspecs declarator
...@@ -733,6 +790,8 @@ explicit_instantiation: ...@@ -733,6 +790,8 @@ explicit_instantiation:
do_function_instantiation (specs, $4, $1); } do_function_instantiation (specs, $4, $1); }
| SCSPEC TEMPLATE notype_declarator | SCSPEC TEMPLATE notype_declarator
{ do_function_instantiation (NULL_TREE, $3, $1); } { do_function_instantiation (NULL_TREE, $3, $1); }
| SCSPEC TEMPLATE constructor_declarator
{ do_function_instantiation (NULL_TREE, $3, $1); }
; ;
/* The TYPENAME expansions are to deal with use of a template class name as /* The TYPENAME expansions are to deal with use of a template class name as
...@@ -2408,15 +2467,26 @@ left_curly: '{' ...@@ -2408,15 +2467,26 @@ left_curly: '{'
} }
; ;
opt.component_decl_list: self_reference:
/* empty */ /* empty */
{ $$ = NULL_TREE; } {
| component_decl_list if (CLASSTYPE_TEMPLATE_INFO (current_class_type))
$$ = NULL_TREE;
else
$$ = build_self_reference ();
}
;
opt.component_decl_list:
self_reference
{ if ($$) $$ = build_tree_list (access_public_node, $$); }
| self_reference component_decl_list
{ {
if (current_aggr == signature_type_node) if (current_aggr == signature_type_node)
$$ = build_tree_list (access_public_node, $$); $$ = build_tree_list (access_public_node, $2);
else else
$$ = build_tree_list (access_default_node, $$); $$ = build_tree_list (access_default_node, $2);
if ($1) $$ = tree_cons (access_public_node, $1, $$);
} }
| opt.component_decl_list VISSPEC ':' component_decl_list | opt.component_decl_list VISSPEC ':' component_decl_list
{ {
...@@ -2488,6 +2558,9 @@ component_decl_1: ...@@ -2488,6 +2558,9 @@ component_decl_1:
| notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init | notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, NULL_TREE, $2, $5, $3, { $$ = grokfield ($$, NULL_TREE, $2, $5, $3,
build_tree_list ($4, NULL_TREE)); } build_tree_list ($4, NULL_TREE)); }
| constructor_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, NULL_TREE, $2, $5, $3,
build_tree_list ($4, NULL_TREE)); }
| ':' expr_no_commas | ':' expr_no_commas
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); } { $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
| error | error
...@@ -2597,6 +2670,12 @@ notype_component_declarator0: ...@@ -2597,6 +2670,12 @@ notype_component_declarator0:
$<ttype>0 = current_declspecs; $<ttype>0 = current_declspecs;
$$ = grokfield ($$, current_declspecs, $2, $5, $3, $$ = grokfield ($$, current_declspecs, $2, $5, $3,
build_tree_list ($4, prefix_attributes)); } build_tree_list ($4, prefix_attributes)); }
| constructor_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
{ split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
$<ttype>0 = current_declspecs;
$$ = grokfield ($$, current_declspecs, $2, $5, $3,
build_tree_list ($4, prefix_attributes)); }
| IDENTIFIER ':' expr_no_commas maybe_attribute | IDENTIFIER ':' expr_no_commas maybe_attribute
{ split_specs_attrs ($<ttype>0, &current_declspecs, { split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes); &prefix_attributes);
...@@ -2781,7 +2860,7 @@ direct_after_type_declarator: ...@@ -2781,7 +2860,7 @@ direct_after_type_declarator:
| '(' after_type_declarator ')' | '(' after_type_declarator ')'
{ $$ = $2; } { $$ = $2; }
| nested_name_specifier type_name %prec EMPTY | nested_name_specifier type_name %prec EMPTY
{ push_nested_class (TREE_TYPE ($$), 3); { push_nested_class ($1, 3);
$$ = build_parse_node (SCOPE_REF, $$, $2); $$ = build_parse_node (SCOPE_REF, $$, $2);
TREE_COMPLEXITY ($$) = current_class_depth; } TREE_COMPLEXITY ($$) = current_class_depth; }
| type_name %prec EMPTY | type_name %prec EMPTY
...@@ -3694,9 +3773,6 @@ complex_parmlist: ...@@ -3694,9 +3773,6 @@ complex_parmlist:
} }
| ELLIPSIS | ELLIPSIS
{ {
/* ARM $8.2.5 has this as a boxed-off comment. */
if (pedantic)
warning ("use of `...' without a first argument is non-portable");
$$ = NULL_TREE; $$ = NULL_TREE;
} }
| TYPENAME_ELLIPSIS | TYPENAME_ELLIPSIS
......
...@@ -114,9 +114,13 @@ process_template_parm (list, next) ...@@ -114,9 +114,13 @@ process_template_parm (list, next)
PARM, 0, NULL_TREE, NULL_TREE); PARM, 0, NULL_TREE, NULL_TREE);
/* A template parameter is not modifiable. */ /* A template parameter is not modifiable. */
TREE_READONLY (parm) = 1; TREE_READONLY (parm) = 1;
if (IS_AGGR_TYPE (TREE_TYPE (parm))) if (IS_AGGR_TYPE (TREE_TYPE (parm))
&& TREE_CODE (TREE_TYPE (parm)) != TEMPLATE_TYPE_PARM)
{ {
sorry ("aggregate template parameter types"); cp_error ("`%#T' is not a valid type for a template constant parameter",
TREE_TYPE (parm));
if (DECL_NAME (parm) == NULL_TREE)
error (" a template type parameter must begin with `class' or `typename'");
TREE_TYPE (parm) = void_type_node; TREE_TYPE (parm) = void_type_node;
} }
tinfo = make_node (TEMPLATE_CONST_PARM); tinfo = make_node (TEMPLATE_CONST_PARM);
...@@ -235,8 +239,10 @@ push_template_decl (decl) ...@@ -235,8 +239,10 @@ push_template_decl (decl)
if (TREE_CODE (decl) == TYPE_DECL) if (TREE_CODE (decl) == TYPE_DECL)
tmpl = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)); tmpl = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
else if (! DECL_TEMPLATE_INFO (decl)) else if (! DECL_TEMPLATE_INFO (decl))
/* A member definition that doesn't match anything in the class. */ {
cp_error ("template definition of non-template `%#D'", decl);
return; return;
}
else else
tmpl = DECL_TI_TEMPLATE (decl); tmpl = DECL_TI_TEMPLATE (decl);
} }
...@@ -609,6 +615,11 @@ lookup_template_class (d1, arglist, in_decl) ...@@ -609,6 +615,11 @@ lookup_template_class (d1, arglist, in_decl)
if (! template) if (! template)
template = IDENTIFIER_CLASS_VALUE (d1); template = IDENTIFIER_CLASS_VALUE (d1);
} }
else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
{
template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d1));
d1 = DECL_NAME (template);
}
else if (TREE_CODE_CLASS (TREE_CODE (d1)) == 't' && IS_AGGR_TYPE (d1)) else if (TREE_CODE_CLASS (TREE_CODE (d1)) == 't' && IS_AGGR_TYPE (d1))
{ {
template = CLASSTYPE_TI_TEMPLATE (d1); template = CLASSTYPE_TI_TEMPLATE (d1);
...@@ -2728,12 +2739,15 @@ do_function_instantiation (declspecs, declarator, storage) ...@@ -2728,12 +2739,15 @@ do_function_instantiation (declspecs, declarator, storage)
} }
/* If we've already seen this template instance, use it. */ /* If we've already seen this template instance, use it. */
if (name = DECL_ASSEMBLER_NAME (decl), if (DECL_FUNCTION_MEMBER_P (decl))
{
if (DECL_TEMPLATE_INSTANTIATION (decl))
result = decl;
else if (name = DECL_ASSEMBLER_NAME (decl),
fn = IDENTIFIER_GLOBAL_VALUE (name), fn = IDENTIFIER_GLOBAL_VALUE (name),
fn && DECL_TEMPLATE_INSTANTIATION (fn)) fn && DECL_TEMPLATE_INSTANTIATION (fn))
result = fn; result = fn;
else if (fn && DECL_CONTEXT (fn)) }
;
else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn) else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn)
{ {
for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn)) for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
...@@ -2779,10 +2793,10 @@ do_function_instantiation (declspecs, declarator, storage) ...@@ -2779,10 +2793,10 @@ do_function_instantiation (declspecs, declarator, storage)
cp_error ("storage class `%D' applied to template instantiation", cp_error ("storage class `%D' applied to template instantiation",
storage); storage);
if (! extern_p)
instantiate_decl (result);
mark_decl_instantiated (result, extern_p); mark_decl_instantiated (result, extern_p);
repo_template_instantiated (result, extern_p); repo_template_instantiated (result, extern_p);
if (! extern_p)
instantiate_decl (result);
} }
void void
......
...@@ -3999,6 +3999,13 @@ build_x_unary_op (code, xarg) ...@@ -3999,6 +3999,13 @@ build_x_unary_op (code, xarg)
return build_opfncall (code, LOOKUP_NORMAL, xarg, return build_opfncall (code, LOOKUP_NORMAL, xarg,
NULL_TREE, NULL_TREE); NULL_TREE, NULL_TREE);
} }
if (code == ADDR_EXPR)
{
if (TREE_CODE (xarg) == TARGET_EXPR)
warning ("taking address of temporary");
}
return build_unary_op (code, xarg, 0); return build_unary_op (code, xarg, 0);
} }
...@@ -4499,17 +4506,30 @@ unary_complex_lvalue (code, arg) ...@@ -4499,17 +4506,30 @@ unary_complex_lvalue (code, arg)
return error_mark_node; return error_mark_node;
} }
/* Add in the offset to the right subobject. */
offset = get_delta_difference (DECL_FIELD_CONTEXT (t), offset = get_delta_difference (DECL_FIELD_CONTEXT (t),
TREE_TYPE (TREE_OPERAND (arg, 0)), TREE_TYPE (TREE_OPERAND (arg, 0)),
0); 0);
/* Add in the offset to the field. */
offset = size_binop (PLUS_EXPR, offset, offset = size_binop (PLUS_EXPR, offset,
size_binop (EASY_DIV_EXPR, size_binop (EASY_DIV_EXPR,
DECL_FIELD_BITPOS (t), DECL_FIELD_BITPOS (t),
size_int (BITS_PER_UNIT))); size_int (BITS_PER_UNIT)));
/* We offset all pointer to data memebers by 1 so that we can
distinguish between a null pointer to data member and the first
data member of a structure. */
offset = size_binop (PLUS_EXPR, offset, size_int (1));
return convert (build_pointer_type (TREE_TYPE (arg)), offset); return convert (build_pointer_type (TREE_TYPE (arg)), offset);
} }
} }
#if 0
/* This seems to be obsolete now (and posssibly wrong, compare with
resolve_offset_ref). */
if (TREE_CODE (arg) == OFFSET_REF) if (TREE_CODE (arg) == OFFSET_REF)
{ {
tree left = TREE_OPERAND (arg, 0), left_addr; tree left = TREE_OPERAND (arg, 0), left_addr;
...@@ -4530,6 +4550,7 @@ unary_complex_lvalue (code, arg) ...@@ -4530,6 +4550,7 @@ unary_complex_lvalue (code, arg)
build1 (NOP_EXPR, integer_type_node, left_addr), build1 (NOP_EXPR, integer_type_node, left_addr),
build1 (NOP_EXPR, integer_type_node, right_addr)); build1 (NOP_EXPR, integer_type_node, right_addr));
} }
#endif
/* We permit compiler to make function calls returning /* We permit compiler to make function calls returning
objects of aggregate type look like lvalues. */ objects of aggregate type look like lvalues. */
...@@ -5558,7 +5579,7 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5558,7 +5579,7 @@ build_modify_expr (lhs, modifycode, rhs)
} }
else else
{ {
cp_error ("no match for `%O(%#T, %#T)'", modifycode, cp_error ("no match for `%Q(%#T, %#T)'", modifycode,
TREE_TYPE (lhs), TREE_TYPE (rhs)); TREE_TYPE (lhs), TREE_TYPE (rhs));
return error_mark_node; return error_mark_node;
} }
...@@ -5567,6 +5588,12 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5567,6 +5588,12 @@ build_modify_expr (lhs, modifycode, rhs)
{ {
lhs = stabilize_reference (lhs); lhs = stabilize_reference (lhs);
newrhs = build_binary_op (modifycode, lhs, rhs, 1); newrhs = build_binary_op (modifycode, lhs, rhs, 1);
if (newrhs == error_mark_node)
{
cp_error (" in evaluation of `%Q(%#T, %#T)'", modifycode,
TREE_TYPE (lhs), TREE_TYPE (rhs));
return error_mark_node;
}
} }
/* Handle a cast used as an "lvalue". /* Handle a cast used as an "lvalue".
...@@ -6977,6 +7004,15 @@ c_expand_return (retval) ...@@ -6977,6 +7004,15 @@ c_expand_return (retval)
&& !TREE_PUBLIC (whats_returned)) && !TREE_PUBLIC (whats_returned))
cp_warning_at ("address of local variable `%D' returned", whats_returned); cp_warning_at ("address of local variable `%D' returned", whats_returned);
} }
else if (TREE_CODE (retval) == VAR_DECL)
{
if (TREE_CODE (TREE_TYPE (retval)) == ARRAY_TYPE
&& DECL_NAME (retval)
&& IDENTIFIER_LOCAL_VALUE (DECL_NAME (retval))
&& !TREE_STATIC (retval)
&& !TREE_PUBLIC (retval))
cp_warning_at ("address of local array `%D' returned", retval);
}
/* Now deal with possible C++ hair: /* Now deal with possible C++ hair:
(1) Compute the return value. (1) Compute the return value.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment