From c91a56d26688ad6ab041f1ba223a975692c9d8c3 Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Tue, 2 Apr 1996 21:44:27 +0000 Subject: [PATCH] 86th Cygnus<->FSF merge From-SVN: r11654 --- gcc/cp/ChangeLog | 126 ++++++++++++++++++++++++++++++++++++++++++++++- gcc/cp/class.c | 96 ++++++++++++++++++++++-------------- gcc/cp/cp-tree.h | 3 +- gcc/cp/decl.c | 45 +++++++++++++---- gcc/cp/error.c | 18 ++++++- gcc/cp/init.c | 40 ++++++++++++--- gcc/cp/parse.y | 112 ++++++++++++++++++++++++++++++++++------- gcc/cp/pt.c | 38 +++++++++----- gcc/cp/typeck.c | 38 +++++++++++++- 9 files changed, 427 insertions(+), 89 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d428c020e63..1548a58b469 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,10 +1,134 @@ -Fri Mar 29 09:41:02 1996 Jeffrey A. Law + + * 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 + + * parse.y (complex_parmlist, ELLIPSES): Take out ARM-based warning. + +Fri Mar 29 15:51:36 1996 Bob Manson + + * 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 + + * pt.c (push_template_decl): Complain about template decl with + inappropriate declaration. + +Fri Mar 29 12:15:35 1996 Bob Manson + + * 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 + + * 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 * 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 + + * 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 + + * 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 + + * 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 + + * init.c (expand_vec_init): Ensure the eh cleanups are on the + function_obstack. + +Wed Mar 27 10:14:30 1996 Jason Merrill + + * 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 + + 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 + + * 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 + + * 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 + + * 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 + + * decl.c (cp_finish_decl): Don't build cleanups for static + variables here. + +Fri Mar 22 17:57:55 1996 Mike Stump + + * 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 + * 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 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index ffe0104656e..76377e14b2e 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1384,7 +1384,7 @@ struct base_info 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. @@ -1520,9 +1520,8 @@ finish_base_struct (t, b, t_binfo) 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)) @@ -2973,7 +2972,7 @@ finish_struct_1 (t, attributes, warn_anon) 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; @@ -3083,7 +3082,7 @@ finish_struct_1 (t, attributes, warn_anon) 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; } @@ -3100,7 +3099,7 @@ finish_struct_1 (t, attributes, warn_anon) 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 @@ -3172,6 +3171,9 @@ finish_struct_1 (t, attributes, warn_anon) { 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) { @@ -3537,7 +3539,7 @@ finish_struct_1 (t, attributes, warn_anon) && !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. */ @@ -3550,11 +3552,6 @@ finish_struct_1 (t, attributes, warn_anon) 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); @@ -3563,7 +3560,7 @@ finish_struct_1 (t, attributes, warn_anon) } 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; @@ -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); 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); } @@ -4212,6 +4209,7 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) tree name = TYPE_NAME (t); tree x, last_x = NULL_TREE; tree access; + tree dummy = NULL_TREE; if (TREE_CODE (name) == TYPE_DECL) { @@ -4233,25 +4231,33 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) 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; @@ -4298,16 +4304,6 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) 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; @@ -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 defined for this type. */ - if (CLASSTYPE_TAGS (t)) + if (CLASSTYPE_TAGS (t) || dummy) { x = CLASSTYPE_TAGS (t); while (x) @@ -4350,6 +4346,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) 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; @@ -5298,6 +5296,7 @@ print_class_statistics () 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 () { @@ -5305,3 +5304,24 @@ 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; +} diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7d9f12cf96e..4f3212c39b8 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1967,6 +1967,7 @@ extern tree instantiate_type PROTO((tree, tree, int)); 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)); @@ -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 *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 */ @@ -2290,7 +2292,6 @@ extern tree lookup_template_class PROTO((tree, tree, tree)); 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)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 10cf2a65047..93585de3db2 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4501,12 +4501,18 @@ lookup_name_real (name, prefer_type, nonclass) 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) @@ -5700,14 +5706,15 @@ shadow_tag (declspecs) { /* 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 { @@ -6525,7 +6532,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) 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); @@ -7676,8 +7685,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli 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; @@ -9030,6 +9042,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli 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; @@ -9064,6 +9079,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli 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; } @@ -10597,15 +10618,19 @@ start_enum (name) 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 diff --git a/gcc/cp/error.c b/gcc/cp/error.c index bb93dd4a17c..652ed3ff0ab 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -34,6 +34,7 @@ typedef char* cp_printer (); #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 @@ -46,7 +47,7 @@ cp_printer * cp_printers[256] = _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */ _, A, _, C, D, E, _, _, _, _, _, _, L, _, _, O, /* 0x40 */ - P, _, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */ + P, Q, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */ }; @@ -56,6 +57,7 @@ cp_printer * cp_printers[256] = #undef L #undef O #undef P +#undef Q #undef T #undef V #undef _ @@ -1503,6 +1505,20 @@ op_as_string (p, v) 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; diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 289cef8e117..b8d0dadde7a 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2071,6 +2071,14 @@ resolve_offset_ref (exp) 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)); @@ -3399,13 +3407,31 @@ expand_vec_init (decl, base, maxindex, init, from_array) 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)); diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index d2b6f95e202..fa521a370f1 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -210,7 +210,7 @@ empty_parms () %type structsp opt.component_decl_list component_decl_list %type component_decl component_decl_1 components notype_components -%type component_declarator component_declarator0 +%type component_declarator component_declarator0 self_reference %type notype_component_declarator notype_component_declarator0 %type after_type_component_declarator after_type_component_declarator0 %type enumlist enumerator @@ -231,7 +231,7 @@ empty_parms () %token PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL %token PRE_PARSED_CLASS_DECL %type fn.def1 /* Not really! */ -%type fn.def2 return_id fn.defpen +%type fn.def2 return_id fn.defpen constructor_declarator %type ctor_initializer_opt %type named_class_head named_class_head_sans_basetype %type named_complex_class_head_sans_basetype @@ -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, $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, $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; @@ -571,6 +616,18 @@ fn.def1: 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 @@ -578,13 +635,6 @@ fn.def1: 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: @@ -608,6 +658,11 @@ fn.def2: $$ = 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 @@ -726,6 +781,8 @@ explicit_instantiation: 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 @@ -733,6 +790,8 @@ explicit_instantiation: 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 @@ -2408,15 +2467,26 @@ left_curly: '{' } ; +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 { @@ -2488,6 +2558,9 @@ component_decl_1: | 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 @@ -2597,6 +2670,12 @@ notype_component_declarator0: $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 ($0, ¤t_declspecs, + &prefix_attributes); + $0 = current_declspecs; + $$ = grokfield ($$, current_declspecs, $2, $5, $3, + build_tree_list ($4, prefix_attributes)); } | IDENTIFIER ':' expr_no_commas maybe_attribute { split_specs_attrs ($0, ¤t_declspecs, &prefix_attributes); @@ -2781,7 +2860,7 @@ direct_after_type_declarator: | '(' 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 @@ -3694,9 +3773,6 @@ complex_parmlist: } | 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 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f3307a1bb91..c4b58a4789a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -114,9 +114,13 @@ process_template_parm (list, next) 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); @@ -235,8 +239,10 @@ push_template_decl (decl) 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); } @@ -609,6 +615,11 @@ lookup_template_class (d1, arglist, in_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); @@ -2728,12 +2739,15 @@ do_function_instantiation (declspecs, declarator, storage) } /* 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)) @@ -2779,10 +2793,10 @@ do_function_instantiation (declspecs, declarator, storage) 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 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 498f293c9c4..05e757f50ee 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -3999,6 +3999,13 @@ build_x_unary_op (code, xarg) 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); } @@ -4499,17 +4506,30 @@ unary_complex_lvalue (code, arg) 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; @@ -4530,6 +4550,7 @@ unary_complex_lvalue (code, arg) 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. */ @@ -5558,7 +5579,7 @@ build_modify_expr (lhs, modifycode, rhs) } 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; } @@ -5567,6 +5588,12 @@ build_modify_expr (lhs, modifycode, rhs) { 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". @@ -6977,6 +7004,15 @@ c_expand_return (retval) && !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. -- 2.30.2