-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.
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>
+ * 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.
* typeck.c (require_complete_type): Be sure to instantiate the
char cant_synth_copy_ctor;
char cant_synth_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.
if (TYPE_VIRTUAL_P (basetype))
{
- /* If there's going to be a destructor needed, make
- sure it will be virtual. */
- b->needs_virtual_dtor = 1;
+ /* Remember that the baseclass has virtual members. */
+ b->base_has_virtual = 1;
/* Don't borrow virtuals from virtual baseclasses. */
if (TREE_VIA_VIRTUAL (base_binfo))
tree fields = TYPE_FIELDS (t);
tree fn_fields = TYPE_METHODS (t);
tree x, last_x, method_vec;
- int needs_virtual_dtor;
+ int base_has_virtual;
int all_virtual;
int has_virtual;
int max_has_virtual;
cant_synth_copy_ctor = base_info.cant_synth_copy_ctor;
cant_synth_asn_ref = base_info.cant_synth_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));
aggregate = 0;
}
cant_synth_copy_ctor = 0;
cant_synth_asn_ref = 0;
no_const_asn_ref = 0;
- needs_virtual_dtor = 0;
+ base_has_virtual = 0;
}
#if 0
{
GNU_xref_member (current_class_name, x);
+ if (TREE_CODE (x) == FIELD_DECL)
+ DECL_PACKED (x) |= TYPE_PACKED (t);
+
/* Handle access declarations. */
if (TREE_CODE (x) == USING_DECL)
{
&& !IS_SIGNATURE (t))
{
/* 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);
/* If we couldn't make it work, then pretend we didn't need it. */
TREE_CHAIN (dtor) = fn_fields;
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))
pending_virtuals = add_virtual_function (pending_virtuals,
&has_virtual, dtor, 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 = 1;
TYPE_NONCOPIED_PARTS (t) = build_tree_list (default_conversion (TYPE_BINFO_VTABLE (t)), vfield);
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",
t);
}
tree name = TYPE_NAME (t);
tree x, last_x = NULL_TREE;
tree access;
+ tree dummy = NULL_TREE;
if (TREE_CODE (name) == TYPE_DECL)
{
if (IS_SIGNATURE (t))
append_signature_fields (list_of_fieldlists);
- if (last_x && list_of_fieldlists)
- TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
-
- /* For signatures, we made all methods `public' in the parser and
- reported an error if a access specifier was used. */
- if (CLASSTYPE_DECLARED_CLASS (t) == 0)
+ /* 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)))
{
- if (list_of_fieldlists
- && TREE_PURPOSE (list_of_fieldlists) == access_default_node)
- TREE_PURPOSE (list_of_fieldlists) = access_public_node;
+ dummy = TREE_VALUE (list_of_fieldlists);
+ list_of_fieldlists = TREE_CHAIN (list_of_fieldlists);
}
- else if (list_of_fieldlists
- && TREE_PURPOSE (list_of_fieldlists) == access_default_node)
- TREE_PURPOSE (list_of_fieldlists) = access_private_node;
+
+ if (last_x && 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
+ reported an error if a access specifier was used. */
+ if (access == access_default_node)
+ {
+ if (CLASSTYPE_DECLARED_CLASS (t) == 0)
+ access = access_public_node;
+ else
+ access = access_private_node;
+ }
+
for (x = TREE_VALUE (list_of_fieldlists); x; x = TREE_CHAIN (x))
{
TREE_PRIVATE (x) = access == access_private_node;
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)
DECL_FIELD_CONTEXT (x) = t;
/* Now add the tags, if any, to the list of TYPE_DECLs
defined for this type. */
- if (CLASSTYPE_TAGS (t))
+ if (CLASSTYPE_TAGS (t) || dummy)
{
x = CLASSTYPE_TAGS (t);
while (x)
x = TREE_CHAIN (x);
last_x = chainon (last_x, tag);
}
+ if (dummy)
+ last_x = chainon (last_x, dummy);
if (fields == NULL_TREE)
fields = last_x;
CLASSTYPE_LOCAL_TYPEDECLS (t) = 1;
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
for this purpose. The effect is undone by pop_obstacks. */
+
void
maybe_push_cache_obstack ()
{
if (current_class_depth == 1)
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;
+}
extern void print_class_statistics PROTO((void));
extern void maybe_push_cache_obstack PROTO((void));
extern unsigned HOST_WIDE_INT skip_rtti_stuff PROTO((tree *));
+extern tree build_self_reference PROTO((void));
/* in cvt.c */
extern tree convert_to_reference PROTO((tree, tree, int, int, tree));
extern char *language_as_string PROTO((enum languages, int));
extern char *parm_as_string PROTO((int, 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));
/* in method.c */
extern int uses_template_parms PROTO((tree));
extern tree instantiate_class_template PROTO((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));
struct tinst_level *tinst_for_decl PROTO((void));
extern void mark_decl_instantiated PROTO((tree, int));
done:
if (val)
{
+ /* This should only warn about types used in qualified-ids. */
if (from_obj && from_obj != val)
{
- cp_pedwarn ("lookup of `%D' in the scope of `%#T' (`%D')",
- name, got_object, from_obj);
- cp_pedwarn (" does not match lookup in the current scope (`%D')",
- val);
+ if (looking_for_typename && TREE_CODE (from_obj) == TYPE_DECL
+ && TREE_CODE (val) == TYPE_DECL
+ && TREE_TYPE (from_obj) != TREE_TYPE (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)
{
/* ANSI C++ June 5 1992 WP 9.5.3. Anonymous unions may not have
function members. */
+ if (TYPE_METHODS (t))
+ error ("an anonymous union cannot have function members");
+
if (TYPE_FIELDS (t))
{
tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
NULL_TREE, NULL_TREE);
finish_anon_union (decl);
}
- else
- error ("anonymous union cannot have a function member");
}
else
{
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 ();
cleanup = maybe_build_cleanup (decl);
ctype = cname;
}
- if (ctype
- && TREE_OPERAND (decl, 1) == constructor_name_full (ctype))
+ if (ctype && TREE_CODE (TREE_OPERAND (decl, 1)) == TYPE_DECL
+ && ((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);
next = &TREE_OPERAND (decl, 1);
decl = *next;
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);
if (IS_SIGNATURE (current_class_type) && opaque_typedef)
SIGNATURE_HAS_OPAQUE_TYPEDECLS (current_class_type) = 1;
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;
}
enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1);
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
{
enumtype = make_node (ENUMERAL_TYPE);
pushtag (name, enumtype, 0);
}
+ if (b->pseudo_global)
+ cp_error ("template declaration of `%#T'", enumtype);
+
if (current_class_type)
TREE_ADDRESSABLE (b->tags) = 1;
+
current_local_enum = NULL_TREE;
/* We copy this value because enumerated type constants
#define L language_as_string
#define O op_as_string
#define P parm_as_string
+#define Q assop_as_string
#define T type_as_string
#define V cv_as_string
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */
_, A, _, C, D, E, _, _, _, _, _, _, L, _, _, O, /* 0x40 */
- P, _, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */
+ P, Q, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */
};
#undef L
#undef O
#undef P
+#undef Q
#undef T
#undef V
#undef _
return buf;
}
+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)
tree p;
addr = convert_pointer_to (basetype, addr);
member = convert (ptrdiff_type_node,
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,
build (PLUS_EXPR, build_pointer_type (type),
addr, member));
use_variable (DECL_RTL (base2));
}
expand_end_loop ();
- if (TYPE_NEEDS_DESTRUCTOR (type))
- end_protect (build_array_eh_cleanup (rval,
- build_binary_op (MINUS_EXPR,
- maxindex,
- iterator,
- 1),
- type));
+ if (TYPE_NEEDS_DESTRUCTOR (type) && flag_handle_exceptions)
+ {
+ /* We have to ensure that this can live to the cleanup
+ expansion time, since we know it is only ever needed
+ once, generate code now. */
+ push_obstacks_nochange ();
+ 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 ();
if (obey_regdecls)
use_variable (DECL_RTL (iterator));
%type <ttype> structsp opt.component_decl_list component_decl_list
%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> after_type_component_declarator after_type_component_declarator0
%type <ttype> enumlist enumerator
%token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL
%token <ttype> PRE_PARSED_CLASS_DECL
%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 <ttype> named_class_head named_class_head_sans_basetype
%type <ttype> named_complex_class_head_sans_basetype
{}
;
+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:
typed_declspecs declarator exception_specification_opt
{ tree specs, attrs;
YYERROR1;
reinit_parse_for_function ();
$$ = 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
fn.def2:
typed_declspecs '(' parmlist ')' type_quals exception_specification_opt
{ 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);
$$ = start_method (TREE_CHAIN (specs), $$, $6);
rest_of_mdef:
$$ = start_method (specs, $2, $3); goto rest_of_mdef; }
| notype_declarator exception_specification_opt
{ $$ = 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
do_function_instantiation (specs, $3, NULL_TREE); }
| TEMPLATE notype_declarator
{ do_function_instantiation (NULL_TREE, $2, NULL_TREE); }
+ | TEMPLATE constructor_declarator
+ { do_function_instantiation (NULL_TREE, $2, NULL_TREE); }
| SCSPEC TEMPLATE aggr template_type
{ do_type_instantiation ($4, $1); }
| SCSPEC TEMPLATE typed_declspecs declarator
do_function_instantiation (specs, $4, $1); }
| SCSPEC TEMPLATE notype_declarator
{ 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
}
;
+self_reference:
+ /* empty */
+ {
+ if (CLASSTYPE_TEMPLATE_INFO (current_class_type))
+ $$ = NULL_TREE;
+ else
+ $$ = build_self_reference ();
+ }
+ ;
+
opt.component_decl_list:
- /* empty */
- { $$ = NULL_TREE; }
- | component_decl_list
+ self_reference
+ { if ($$) $$ = build_tree_list (access_public_node, $$); }
+ | self_reference component_decl_list
{
if (current_aggr == signature_type_node)
- $$ = build_tree_list (access_public_node, $$);
+ $$ = build_tree_list (access_public_node, $2);
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
{
| notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, NULL_TREE, $2, $5, $3,
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
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
| error
$<ttype>0 = current_declspecs;
$$ = grokfield ($$, current_declspecs, $2, $5, $3,
build_tree_list ($4, prefix_attributes)); }
+ | constructor_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
+ { split_specs_attrs ($<ttype>0, ¤t_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
{ split_specs_attrs ($<ttype>0, ¤t_declspecs,
&prefix_attributes);
| '(' after_type_declarator ')'
{ $$ = $2; }
| nested_name_specifier type_name %prec EMPTY
- { push_nested_class (TREE_TYPE ($$), 3);
+ { push_nested_class ($1, 3);
$$ = build_parse_node (SCOPE_REF, $$, $2);
TREE_COMPLEXITY ($$) = current_class_depth; }
| type_name %prec EMPTY
}
| 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;
}
| TYPENAME_ELLIPSIS
PARM, 0, NULL_TREE, NULL_TREE);
/* A template parameter is not modifiable. */
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;
}
tinfo = make_node (TEMPLATE_CONST_PARM);
if (TREE_CODE (decl) == TYPE_DECL)
tmpl = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
else if (! DECL_TEMPLATE_INFO (decl))
- /* A member definition that doesn't match anything in the class. */
- return;
+ {
+ cp_error ("template definition of non-template `%#D'", decl);
+ return;
+ }
else
tmpl = DECL_TI_TEMPLATE (decl);
}
if (! template)
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))
{
template = CLASSTYPE_TI_TEMPLATE (d1);
}
/* 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 (fn && DECL_CONTEXT (fn))
- ;
+ 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 && 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))
cp_error ("storage class `%D' applied to template instantiation",
storage);
- if (! extern_p)
- instantiate_decl (result);
mark_decl_instantiated (result, extern_p);
repo_template_instantiated (result, extern_p);
+ if (! extern_p)
+ instantiate_decl (result);
}
void
return build_opfncall (code, LOOKUP_NORMAL, xarg,
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 error_mark_node;
}
+ /* Add in the offset to the right subobject. */
offset = get_delta_difference (DECL_FIELD_CONTEXT (t),
TREE_TYPE (TREE_OPERAND (arg, 0)),
0);
+
+ /* Add in the offset to the field. */
offset = size_binop (PLUS_EXPR, offset,
size_binop (EASY_DIV_EXPR,
DECL_FIELD_BITPOS (t),
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);
}
}
+
+#if 0
+ /* This seems to be obsolete now (and posssibly wrong, compare with
+ resolve_offset_ref). */
if (TREE_CODE (arg) == OFFSET_REF)
{
tree left = TREE_OPERAND (arg, 0), left_addr;
build1 (NOP_EXPR, integer_type_node, left_addr),
build1 (NOP_EXPR, integer_type_node, right_addr));
}
+#endif
/* We permit compiler to make function calls returning
objects of aggregate type look like lvalues. */
}
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));
return error_mark_node;
}
{
lhs = stabilize_reference (lhs);
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".
&& !TREE_PUBLIC (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:
(1) Compute the return value.