diff options
author | Mike Stump <mrs@gcc.gnu.org> | 1996-01-17 18:57:55 +0000 |
---|---|---|
committer | Mike Stump <mrs@gcc.gnu.org> | 1996-01-17 18:57:55 +0000 |
commit | be99da7733a890fb35dd3d8cf4ae1852581f5b1d (patch) | |
tree | 35917201c2e79bcd4b979c022dbc9be8b0628be0 | |
parent | 3a265431763860a5381416371d38e2d602cfdaaf (diff) | |
download | gcc-be99da7733a890fb35dd3d8cf4ae1852581f5b1d.zip gcc-be99da7733a890fb35dd3d8cf4ae1852581f5b1d.tar.gz gcc-be99da7733a890fb35dd3d8cf4ae1852581f5b1d.tar.bz2 |
78th Cygnus<->FSF merge
From-SVN: r11039
-rw-r--r-- | gcc/cp/ChangeLog | 136 | ||||
-rw-r--r-- | gcc/cp/call.c | 23 | ||||
-rw-r--r-- | gcc/cp/class.c | 64 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 21 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 23 | ||||
-rw-r--r-- | gcc/cp/decl.c | 417 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 6 | ||||
-rw-r--r-- | gcc/cp/except.c | 102 | ||||
-rw-r--r-- | gcc/cp/gxxint.texi | 40 | ||||
-rw-r--r-- | gcc/cp/init.c | 155 | ||||
-rw-r--r-- | gcc/cp/lex.c | 18 | ||||
-rw-r--r-- | gcc/cp/method.c | 12 | ||||
-rw-r--r-- | gcc/cp/parse.y | 99 | ||||
-rw-r--r-- | gcc/cp/pt.c | 7 | ||||
-rw-r--r-- | gcc/cp/search.c | 107 | ||||
-rw-r--r-- | gcc/cp/sig.c | 2 | ||||
-rw-r--r-- | gcc/cp/tree.c | 7 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 30 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 68 |
19 files changed, 741 insertions, 596 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a1722c2..22cb2b3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,137 @@ +Wed Jan 17 10:18:01 1996 Mike Stump <mrs@cygnus.com> + + * decl2.c (warn_pointer_arith): Default to on. + +Tue Jan 16 12:45:38 1996 Jason Merrill <jason@yorick.cygnus.com> + + * lex.c (is_rid): New function. + * decl.c (grokdeclarator): Diagnose reserved words used as + declarator-ids. + +Tue Jan 16 11:39:40 1996 Jason Merrill <jason@yorick.cygnus.com> + + * tree.c (get_decl_list): Don't lose cv-quals. + + * decl.c (grokdeclarator): Fix SCOPE_REF handling and diagnose + typespecs used as declarator-ids. + +Tue Jan 16 11:09:42 1996 Mike Stump <mrs@cygnus.com> + + * decl.c (poplevel): When poping a level, don't give a warning for + any subblocks that already exist. + +Tue Jan 16 00:25:33 1996 Jason Merrill <jason@yorick.cygnus.com> + + * typeck.c (build_object_ref): Finish what I started. + + * parse.y (qualified_type_name): Don't check TYPE_BUILT_IN. + + * decl2.c (constructor_name_full): Handle TEMPLATE_TYPE_PARMs. + + * decl.c (grokdeclarator): Also accept TEMPLATE_TYPE_PARM as a + scope. + +Mon Jan 15 16:19:32 1996 Jason Merrill <jason@yorick.cygnus.com> + + * decl.c (xref_tag): Handle passing a type in directly. + + * parse.y (qualified_type_name): Pull out the type. + (nested_type): Ditto. + Take types directly instead of as identifiers. + * call.c (build_scoped_method_call): Take types directly instead of + as identifiers. + * decl.c (xref_basetypes): Ditto. + * init.c (expand_member_init): Ditto. + (build_member_call): Ditto. + (build_offset_ref): Ditto. + * typeck2.c (build_scoped_ref): Ditto, remove bogus code. + * method.c (do_build_assign_ref): Ditto. + * decl.c (grokdeclarator): Handle a type appearing as the + declarator-id for constructors. + * method.c (do_build_copy_constructor): current_base_init_list now + uses the types directly, not their names. + * init.c (sort_base_init): Ditto. + (expand_member_init): Ditto. + * init.c (is_aggr_type): New function, like is_aggr_typedef. + * class.c (pushclass): If !modify and + CLASSTYPE_LOCAL_TYPEDECLS (type)), do set up IDENTIFIER_TYPE_VALUE + for inherited types. + +Mon Jan 15 08:45:01 1996 Jeffrey A Law (law@cygnus.com) + + * tree.c (layout_basetypes): Call build_lang_field_decl instead + of build_lang_decl if first arg is a FIELD_DECL. + (tree_copy_lang_decl_for_deferred_output): Reverse test for when + to copy DECL_MAIN_VARIANT and DECL_CHAIN. + +Thu Jan 11 14:55:07 1996 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (cp_finish_decl): Only clear TREE_USED if DECL_NAME is + non-empty. + * except.c (expand_start_catch_block): Set TREE_USED to avoid + warnings about the catch handler. + +Mon Jan 8 17:35:12 1996 Jason Merrill <jason@yorick.cygnus.com> + + * typeck.c (build_modify_expr): Use a COMPOUND_EXPR instead of + expand_target_expr. + +Thu Jan 4 12:30:32 1996 Brendan Kehoe <brendan@lisa.cygnus.com> + + Fix access control to use trees rather than integers. + * class.c (access_{default, public, protected, private, + default_virtual, public_virtual, private_virtual}_node): Add + definitions. + (init_class_processing): Do creation of those nodes. + * cp-tree.h (access_type): Delete enum decl. + (access_{default, public, protected, private, default_virtual, + public_virtual, private_virtual}_node): Add decls. + (compute_access): Change return type. + * search.c (compute_access): Have tree return type, instead of enum. + (lookup_field): Declare THIS_V and NEW_V to be tree nodes. + * lex.c (real_yylex): Use yylval.ttype for giving the value of the + access_* node for each of RID_{PUBLIC, PRIVATE, PROTECTED}. + * parse.y (VISSPEC): Make ttype rather than itype. + (base_class_access_list): Likewise. + * *.[cy]: Change all refs of `access_public' to `access_public_node', + etc. + * call.c (build_method_call): Make ACCESS be a tree. + * class.c (alter_access, finish_struct_1, filter_struct): Likewise. + * cvt.c (convert_to_aggr): Likewise. + * init.c (build_offset_ref, resolve_offset_ref, build_delete): + Likewise. + * method.c (hack_identifier): Likewise. + * typeck.c (build_component_ref_1, build_component_ref): ): Likewise. + +Thu Jan 4 11:02:20 1996 Mike Stump <mrs@cygnus.com> + + * typeck.c (pointer_int_sum, pointer_diff): Make code agree with C + frontend, and make it more consistent with respect to + warn_pointer_arith. + +Tue Jan 2 00:13:38 1996 Rusty Russell <rusty@adelaide.maptek.com.au> + + * decl.c (pushdecl): Check for duplicate parameter names. + +Wed Jan 3 09:25:48 1996 Mike Stump <mrs@cygnus.com> + + * decl.c (expand_static_init): Call assemble_external for atexit. + +Wed Jan 3 07:55:19 1996 Mike Stump <mrs@cygnus.com> + + * except.c (do_unwind): Remove some generated dead code. + (eh_outer_context): New routine, factor out some common code from + expand_builtin_throw and end_eh_unwinder. Add code to do return + address masking for the PA. + (expand_builtin_throw): Use eh_outer_context instead of open coding + it here. + (end_eh_unwinder): Ditto. + +Tue Jan 2 17:00:56 1996 Mike Stump <mrs@cygnus.com> + + * except.c (expand_throw): Call assemble_external for __empty, if we + use it. + Thu Dec 28 11:13:15 1995 Mike Stump <mrs@cygnus.com> * except.c (expand_builtin_throw): Use RETURN_ADDR_OFFSET instead of @@ -3977,7 +4111,7 @@ Fri Dec 9 18:17:37 1994 Doug Evans <dje@cygnus.com> (PARSE_H): Depend on $(PARSE_C), for parallel makes. (PARSE_C): Undo last patch. -Fri Dec 2 10:44:36 1994 Mike Stump (mrs@wombat.gnu.ai.mit.edu) +Fri Dec 2 10:44:36 1994 Mike Stump <mrs@cygnus.com> * Makefile.in (BISONFLAGS): Add --yacc so that output winds up in y.tab.c. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 973deaa..cbe5588 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -1461,8 +1461,8 @@ resolve_scope_to_name (outer_type, inner_stuff) /* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'. This is how virtual function calls are avoided. */ tree -build_scoped_method_call (exp, scopes, name, parms) - tree exp, scopes, name, parms; +build_scoped_method_call (exp, basetype, name, parms) + tree exp, basetype, name, parms; { /* Because this syntactic form does not allow a pointer to a base class to be `stolen', @@ -1470,23 +1470,20 @@ build_scoped_method_call (exp, scopes, name, parms) that happens here. @@ But we do have to check access privileges later. */ - tree basename = resolve_scope_to_name (NULL_TREE, scopes); - tree basetype, binfo, decl; + tree binfo, decl; tree type = TREE_TYPE (exp); if (type == error_mark_node - || basename == NULL_TREE) + || basetype == error_mark_node) return error_mark_node; - basetype = IDENTIFIER_TYPE_VALUE (basename); - if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note that explicit ~int is caught in the parser; this deals with typedefs and template parms. */ - if (TREE_CODE (name) == BIT_NOT_EXPR && ! is_aggr_typedef (basename, 0)) + if (TREE_CODE (name) == BIT_NOT_EXPR && ! IS_AGGR_TYPE (basetype)) { if (type != basetype) cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')", @@ -1498,7 +1495,7 @@ build_scoped_method_call (exp, scopes, name, parms) return convert (void_type_node, exp); } - if (! is_aggr_typedef (basename, 1)) + if (! is_aggr_type (basetype, 1)) return error_mark_node; if (! IS_AGGR_TYPE (type)) @@ -1516,7 +1513,7 @@ build_scoped_method_call (exp, scopes, name, parms) decl = build_indirect_ref (convert_pointer_to (binfo, build_unary_op (ADDR_EXPR, exp, 0)), NULL_PTR); else - decl = build_scoped_ref (exp, scopes); + decl = build_scoped_ref (exp, basetype); /* Call to a destructor. */ if (TREE_CODE (name) == BIT_NOT_EXPR) @@ -1613,7 +1610,7 @@ build_method_call (instance, name, parms, basetype_path, flags) register tree baselink, result, method_name, parmtypes, parm; tree last; int pass; - enum access_type access = access_public; + tree access = access_public_node; /* Range of cases for vtable optimization. */ enum vtable_needs { not_needed, maybe_needed, unneeded, needed }; @@ -2422,7 +2419,7 @@ build_method_call (instance, name, parms, basetype_path, flags) if (flags & LOOKUP_PROTECT) access = compute_access (basetype_path, function); - if (access == access_private) + if (access == access_private_node) { if (flags & LOOKUP_COMPLAIN) { @@ -2433,7 +2430,7 @@ build_method_call (instance, name, parms, basetype_path, flags) } return error_mark_node; } - else if (access == access_protected) + else if (access == access_protected_node) { if (flags & LOOKUP_COMPLAIN) { diff --git a/gcc/cp/class.c b/gcc/cp/class.c index fc25b1a..cca35da 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -98,6 +98,15 @@ char *dont_allow_type_definitions; via this node. */ static tree base_layout_decl; +/* Constants used for access control. */ +tree access_default_node; /* 0 */ +tree access_public_node; /* 1 */ +tree access_protected_node; /* 2 */ +tree access_private_node; /* 3 */ +tree access_default_virtual_node; /* 4 */ +tree access_public_virtual_node; /* 5 */ +tree access_private_virtual_node; /* 6 */ + /* Variables shared between class.c and call.c. */ int n_vtables = 0; @@ -1108,10 +1117,10 @@ static int alter_access (t, fdecl, access) tree t; tree fdecl; - enum access_type access; + tree access; { tree elem = purpose_member (t, DECL_ACCESS (fdecl)); - if (elem && TREE_VALUE (elem) != (tree)access) + if (elem && TREE_VALUE (elem) != access) { if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL) { @@ -1123,25 +1132,24 @@ alter_access (t, fdecl, access) } else if (TREE_PRIVATE (fdecl)) { - if (access != access_private) + if (access != access_private_node) cp_error_at ("cannot make private `%D' non-private", fdecl); goto alter; } else if (TREE_PROTECTED (fdecl)) { - if (access != access_protected) + if (access != access_protected_node) cp_error_at ("cannot make protected `%D' non-protected", fdecl); goto alter; } /* ARM 11.3: an access declaration may not be used to restrict access to a member that is accessible in the base class. */ - else if (access != access_public) + else if (access != access_public_node) cp_error_at ("cannot reduce access of public member `%D'", fdecl); else if (elem == NULL_TREE) { alter: - DECL_ACCESS (fdecl) = tree_cons (t, (tree)access, - DECL_ACCESS (fdecl)); + DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl)); return 1; } return 0; @@ -2957,16 +2965,16 @@ finish_struct_1 (t, warn_anon) if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF) { tree fdecl = TREE_OPERAND (DECL_NAME (x), 1); - enum access_type access - = TREE_PRIVATE (x) ? access_private : - TREE_PROTECTED (x) ? access_protected : access_public; + tree access + = TREE_PRIVATE (x) ? access_private_node : + TREE_PROTECTED (x) ? access_protected_node : access_public_node; if (last_x) TREE_CHAIN (last_x) = TREE_CHAIN (x); else fields = TREE_CHAIN (x); - access_decls = tree_cons ((tree) access, fdecl, access_decls); + access_decls = tree_cons (access, fdecl, access_decls); continue; } @@ -3411,7 +3419,7 @@ finish_struct_1 (t, warn_anon) tree fdecl = TREE_VALUE (access_decls); tree flist = NULL_TREE; tree name; - enum access_type access = (enum access_type)TREE_PURPOSE(access_decls); + tree access = TREE_PURPOSE(access_decls); int i = TREE_VEC_ELT (method_vec, 0) ? 0 : 1; tree tmp; @@ -4053,7 +4061,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) tree *tail = &TYPE_METHODS (t); tree name = TYPE_NAME (t); tree x, last_x = NULL_TREE; - enum access_type access; + tree access; if (TREE_CODE (name) == TYPE_DECL) { @@ -4083,21 +4091,21 @@ finish_struct (t, list_of_fieldlists, warn_anon) if (CLASSTYPE_DECLARED_CLASS (t) == 0) { if (list_of_fieldlists - && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default) - TREE_PURPOSE (list_of_fieldlists) = (tree)access_public; + && TREE_PURPOSE (list_of_fieldlists) == access_default_node) + TREE_PURPOSE (list_of_fieldlists) = access_public_node; } else if (list_of_fieldlists - && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default) - TREE_PURPOSE (list_of_fieldlists) = (tree)access_private; + && TREE_PURPOSE (list_of_fieldlists) == access_default_node) + TREE_PURPOSE (list_of_fieldlists) = access_private_node; while (list_of_fieldlists) { - access = (enum access_type)TREE_PURPOSE (list_of_fieldlists); + access = TREE_PURPOSE (list_of_fieldlists); for (x = TREE_VALUE (list_of_fieldlists); x; x = TREE_CHAIN (x)) { - TREE_PRIVATE (x) = access == access_private; - TREE_PROTECTED (x) = access == access_protected; + TREE_PRIVATE (x) = access == access_private_node; + TREE_PROTECTED (x) = access == access_protected_node; /* Check for inconsistent use of this name in the class body. Enums, types and static vars have already been checked. */ @@ -4306,6 +4314,14 @@ init_class_processing () current_lang_base = (tree *)xmalloc(current_lang_stacksize * sizeof (tree)); current_lang_stack = current_lang_base; + access_default_node = build_int_2 (0, 0); + access_public_node = build_int_2 (1, 0); + access_protected_node = build_int_2 (2, 0); + access_private_node = build_int_2 (3, 0); + access_default_virtual_node = build_int_2 (4, 0); + access_public_virtual_node = build_int_2 (5, 0); + access_private_virtual_node = build_int_2 (6, 0); + /* Keep these values lying around. */ the_null_vtable_entry = build_vtable_entry (integer_zero_node, integer_zero_node); base_layout_decl = build_lang_field_decl (FIELD_DECL, NULL_TREE, error_mark_node); @@ -4400,7 +4416,7 @@ pushclass (type, modify) else if (type != previous_class_type || current_class_depth > 1) { build_mi_matrix (type); - push_class_decls (type); + push_class_decls (type, !modify); free_mi_matrix (); if (current_class_depth == 1) previous_class_type = type; @@ -4437,6 +4453,12 @@ pushclass (type, modify) current_function_decl = this_fndecl; } + else if (CLASSTYPE_LOCAL_TYPEDECLS (type)) + { + build_mi_matrix (type); + push_class_decls (type, !modify); + free_mi_matrix (); + } if (flag_cadillac) cadillac_push_class (type); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ddea575..6ad5ea0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1727,15 +1727,14 @@ extern int current_function_parms_stored; can have. These are sensible combinations of {public,private,protected} cross {virtual,non-virtual}. */ -enum access_type { - access_default, - access_public, - access_protected, - access_private, - access_default_virtual, - access_public_virtual, - access_private_virtual -}; +/* in class.c. */ +extern tree access_default_node; /* 0 */ +extern tree access_public_node; /* 1 */ +extern tree access_protected_node; /* 2 */ +extern tree access_private_node; /* 3 */ +extern tree access_default_virtual_node; /* 4 */ +extern tree access_public_virtual_node; /* 5 */ +extern tree access_private_virtual_node; /* 6 */ /* in lex.c */ extern tree current_unit_name, current_unit_language; @@ -2311,7 +2310,7 @@ extern void push_memoized_context PROTO((tree, int)); extern void pop_memoized_context PROTO((int)); extern tree get_binfo PROTO((tree, tree, int)); extern int get_base_distance PROTO((tree, tree, int, tree *)); -extern enum access_type compute_access PROTO((tree, tree)); +extern tree compute_access PROTO((tree, tree)); extern tree lookup_field PROTO((tree, tree, int, int)); extern tree lookup_nested_field PROTO((tree, int)); extern tree lookup_fnfields PROTO((tree, tree, int)); @@ -2333,7 +2332,7 @@ extern void build_mi_virtuals PROTO((int, int)); extern void add_mi_virtuals PROTO((int, tree)); extern void report_ambiguous_mi_virtuals PROTO((int, tree)); extern void note_debug_info_needed PROTO((tree)); -extern void push_class_decls PROTO((tree)); +extern void push_class_decls PROTO((tree, int)); extern void pop_class_decls PROTO((tree)); extern void unuse_fields PROTO((tree)); extern void unmark_finished_struct PROTO((tree)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index a4e28ff..c135bba 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -896,8 +896,7 @@ convert_to_aggr (type, expr, msgp, protect) tree basetype = type; tree name = TYPE_IDENTIFIER (basetype); tree function, fndecl, fntype, parmtypes, parmlist, result; - tree method_name; - enum access_type access; + tree method_name, access; int can_be_private, can_be_protected; if (! TYPE_HAS_CONSTRUCTOR (basetype)) @@ -907,7 +906,7 @@ convert_to_aggr (type, expr, msgp, protect) return error_mark_node; } - access = access_public; + access = access_public_node; can_be_private = 0; can_be_protected = IDENTIFIER_CLASS_VALUE (name) || name == current_class_name; @@ -987,20 +986,20 @@ convert_to_aggr (type, expr, msgp, protect) if (protect) { if (TREE_PRIVATE (fndecl)) - access = access_private; + access = access_private_node; else if (TREE_PROTECTED (fndecl)) - access = access_protected; + access = access_protected_node; else - access = access_public; + access = access_public_node; } else - access = access_public; + access = access_public_node; - if (access == access_private + if (access == access_private_node ? (basetype == current_class_type || is_friend (basetype, cp->function) || purpose_member (basetype, DECL_ACCESS (fndecl))) - : access == access_protected + : access == access_protected_node ? (can_be_protected || purpose_member (basetype, DECL_ACCESS (fndecl))) : 1) @@ -1011,7 +1010,7 @@ convert_to_aggr (type, expr, msgp, protect) } else { - if (access == access_private) + if (access == access_private_node) saw_private = 1; else saw_protected = 1; @@ -1061,7 +1060,7 @@ convert_to_aggr (type, expr, msgp, protect) /* NOTREACHED */ found: - if (access == access_private) + if (access == access_private_node) if (! can_be_private) { if (msgp) @@ -1070,7 +1069,7 @@ convert_to_aggr (type, expr, msgp, protect) : "conversion to type `%s' is from private base class"; return error_mark_node; } - if (access == access_protected) + if (access == access_protected_node) if (! can_be_protected) { if (msgp) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 869d853..49eb67e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1104,17 +1104,22 @@ poplevel (keep, reverse, functionbody) { if (decls || tags || subblocks) { - if (BLOCK_VARS (block) || BLOCK_TYPE_TAGS (block) || BLOCK_SUBBLOCKS (block)) + if (BLOCK_VARS (block) || BLOCK_TYPE_TAGS (block)) { warning ("internal compiler error: debugging info corrupted"); } BLOCK_VARS (block) = decls; BLOCK_TYPE_TAGS (block) = tags; - /* Recover from too many blocks by chaining them together. */ - BLOCK_SUBBLOCKS (block) = chainon (BLOCK_SUBBLOCKS (block), subblocks); + + /* We can have previous subblocks and new subblocks when + doing fixup_gotos with complex cleanups. We chain the new + subblocks onto the end of any pre-existing subblocks. */ + BLOCK_SUBBLOCKS (block) = chainon (BLOCK_SUBBLOCKS (block), + subblocks); } - /* If we created the block earlier on, and we are just diddling it now, then - it already should have a proper BLOCK_END_NOTE value associated with it. */ + /* If we created the block earlier on, and we are just + diddling it now, then it already should have a proper + BLOCK_END_NOTE value associated with it. */ } else { @@ -3140,6 +3145,10 @@ pushdecl (x) { if (DECL_CONTEXT (t) == NULL_TREE) fatal ("parse errors have confused me too much"); + + /* Check for duplicate params. */ + if (duplicate_decls (x, t)) + return t; } else if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c) || (TREE_CODE (x) == TEMPLATE_DECL @@ -6909,7 +6918,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) was initialized was ever used. Don't do this if it has a destructor, so we don't complain about the 'resource allocation is initialization' idiom. */ - if (TYPE_NEEDS_CONSTRUCTING (type) && cleanup == NULL_TREE) + if (TYPE_NEEDS_CONSTRUCTING (type) + && cleanup == NULL_TREE + && DECL_NAME (decl)) TREE_USED (decl) = 0; /* Store the cleanup, if there was one. */ @@ -7069,6 +7080,7 @@ expand_static_init (decl, init) build_function_type (void_type_node, pfvlist), NOT_BUILT_IN, NULL_PTR); + assemble_external (atexit_fndecl); Atexit = default_conversion (atexit_fndecl); pop_lang_context (); pop_obstacks (); @@ -7690,222 +7702,211 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli /* Look inside a declarator for the name being declared and get it as a string, for an error message. */ { - tree last = NULL_TREE; - register tree decl = declarator; + tree *next = &declarator; + register tree decl; name = NULL; - while (decl) - switch (TREE_CODE (decl)) - { - case COND_EXPR: - ctype = NULL_TREE; - decl = TREE_OPERAND (decl, 0); - break; - - case BIT_NOT_EXPR: /* for C++ destructors! */ + while (next && *next) + { + decl = *next; + switch (TREE_CODE (decl)) { - tree name = TREE_OPERAND (decl, 0); - tree rename = NULL_TREE; - - my_friendly_assert (flags == NO_SPECIAL, 152); - flags = DTOR_FLAG; - return_type = return_dtor; - my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153); - if (ctype == NULL_TREE) - { - if (current_class_type == NULL_TREE) - { - error ("destructors must be member functions"); - flags = NO_SPECIAL; - } - else - { - tree t = constructor_name (current_class_name); - if (t != name) - rename = t; - } - } - else - { - tree t = constructor_name (ctype); - if (t != name) - rename = t; - } - - if (rename) - { - error ("destructor `%s' must match class name `%s'", - IDENTIFIER_POINTER (name), - IDENTIFIER_POINTER (rename)); - TREE_OPERAND (decl, 0) = rename; - } - decl = name; - } - break; - - case ADDR_EXPR: /* C++ reference declaration */ - /* fall through */ - case ARRAY_REF: - case INDIRECT_REF: - ctype = NULL_TREE; - innermost_code = TREE_CODE (decl); - last = decl; - decl = TREE_OPERAND (decl, 0); - break; + case COND_EXPR: + ctype = NULL_TREE; + next = &TREE_OPERAND (decl, 0); + break; - case CALL_EXPR: - if (parmlist_is_exprlist (TREE_OPERAND (decl, 1))) + case BIT_NOT_EXPR: /* for C++ destructors! */ { - /* This is actually a variable declaration using constructor - syntax. We need to call start_decl and cp_finish_decl so we - can get the variable initialized... */ - - if (last) - /* We need to insinuate ourselves into the declarator in place - of the CALL_EXPR. */ - TREE_OPERAND (last, 0) = TREE_OPERAND (decl, 0); + tree name = TREE_OPERAND (decl, 0); + tree rename = NULL_TREE; + + my_friendly_assert (flags == NO_SPECIAL, 152); + flags = DTOR_FLAG; + return_type = return_dtor; + my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153); + if (ctype == NULL_TREE) + { + if (current_class_type == NULL_TREE) + { + error ("destructors must be member functions"); + flags = NO_SPECIAL; + } + else + { + tree t = constructor_name (current_class_name); + if (t != name) + rename = t; + } + } else - declarator = TREE_OPERAND (decl, 0); - - init = TREE_OPERAND (decl, 1); - - decl = start_decl (declarator, declspecs, 1, NULL_TREE); - finish_decl (decl, init, NULL_TREE); - return 0; - } - innermost_code = TREE_CODE (decl); - if (decl_context == FIELD && ctype == NULL_TREE) - ctype = current_class_type; - if (ctype - && TREE_OPERAND (decl, 0) == constructor_name_full (ctype)) - TREE_OPERAND (decl, 0) = constructor_name (ctype); - decl = TREE_OPERAND (decl, 0); - if (ctype != NULL_TREE - && decl != NULL_TREE && flags != DTOR_FLAG - && decl == constructor_name (ctype)) - { - return_type = return_ctor; - ctor_return_type = ctype; - } - ctype = NULL_TREE; - break; - - case IDENTIFIER_NODE: - dname = decl; - decl = NULL_TREE; + { + tree t = constructor_name (ctype); + if (t != name) + rename = t; + } - if (! IDENTIFIER_OPNAME_P (dname) - /* Linux headers use '__op'. Arrgh. */ - || IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname)) - name = IDENTIFIER_POINTER (dname); - else - { - if (IDENTIFIER_TYPENAME_P (dname)) + if (rename) { - my_friendly_assert (flags == NO_SPECIAL, 154); - flags = TYPENAME_FLAG; - ctor_return_type = TREE_TYPE (dname); - return_type = return_conversion; + error ("destructor `%s' must match class name `%s'", + IDENTIFIER_POINTER (name), + IDENTIFIER_POINTER (rename)); + TREE_OPERAND (decl, 0) = rename; } - name = operator_name_string (dname); + next = &name; } - break; + break; - case RECORD_TYPE: - case UNION_TYPE: - case ENUMERAL_TYPE: - /* Parse error puts this typespec where - a declarator should go. */ - error ("declarator name missing"); - dname = TYPE_NAME (decl); - if (dname && TREE_CODE (dname) == TYPE_DECL) - dname = DECL_NAME (dname); - name = dname ? IDENTIFIER_POINTER (dname) : "<nameless>"; - declspecs = temp_tree_cons (NULL_TREE, decl, declspecs); - decl = NULL_TREE; - break; + case ADDR_EXPR: /* C++ reference declaration */ + /* fall through */ + case ARRAY_REF: + case INDIRECT_REF: + ctype = NULL_TREE; + innermost_code = TREE_CODE (decl); + next = &TREE_OPERAND (decl, 0); + break; - /* C++ extension */ - case SCOPE_REF: - { - /* Perform error checking, and convert class names to types. - We may call grokdeclarator multiple times for the same - tree structure, so only do the conversion once. In this - case, we have exactly what we want for `ctype'. */ - tree cname = TREE_OPERAND (decl, 0); - if (cname == NULL_TREE) - ctype = NULL_TREE; - /* Can't use IS_AGGR_TYPE because CNAME might not be a type. */ - else if (IS_AGGR_TYPE_CODE (TREE_CODE (cname)) - || TREE_CODE (cname) == UNINSTANTIATED_P_TYPE) - ctype = cname; - else if (! is_aggr_typedef (cname, 1)) + case CALL_EXPR: + if (parmlist_is_exprlist (TREE_OPERAND (decl, 1))) { - TREE_OPERAND (decl, 0) = NULL_TREE; + /* This is actually a variable declaration using constructor + syntax. We need to call start_decl and cp_finish_decl so we + can get the variable initialized... */ + + *next = TREE_OPERAND (decl, 0); + init = TREE_OPERAND (decl, 1); + + decl = start_decl (declarator, declspecs, 1, NULL_TREE); + finish_decl (decl, init, NULL_TREE); + return 0; } - /* Must test TREE_OPERAND (decl, 1), in case user gives - us `typedef (class::memfunc)(int); memfunc *memfuncptr;' */ - else if (TREE_OPERAND (decl, 1) - && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF) + innermost_code = TREE_CODE (decl); + if (decl_context == FIELD && ctype == NULL_TREE) + ctype = current_class_type; + if (ctype && TREE_OPERAND (decl, 0) == ctype) + TREE_OPERAND (decl, 0) = constructor_name (ctype); + next = &TREE_OPERAND (decl, 0); + decl = *next; + if (ctype != NULL_TREE + && decl != NULL_TREE && flags != DTOR_FLAG + && decl == constructor_name (ctype)) { - TREE_OPERAND (decl, 0) = IDENTIFIER_TYPE_VALUE (cname); + return_type = return_ctor; + ctor_return_type = ctype; } - else if (ctype == NULL_TREE) + ctype = NULL_TREE; + break; + + case IDENTIFIER_NODE: + dname = decl; + next = 0; + + if (is_rid (dname)) { - ctype = IDENTIFIER_TYPE_VALUE (cname); - TREE_OPERAND (decl, 0) = ctype; + cp_error ("declarator-id missing; using reserved word `%D'", + dname); + name = IDENTIFIER_POINTER (dname); } - else if (TREE_COMPLEXITY (decl) == current_class_depth) - TREE_OPERAND (decl, 0) = ctype; + if (! IDENTIFIER_OPNAME_P (dname) + /* Linux headers use '__op'. Arrgh. */ + || IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname)) + name = IDENTIFIER_POINTER (dname); else { - if (! UNIQUELY_DERIVED_FROM_P (IDENTIFIER_TYPE_VALUE (cname), - ctype)) + if (IDENTIFIER_TYPENAME_P (dname)) { - cp_error ("type `%T' is not derived from type `%T'", - IDENTIFIER_TYPE_VALUE (cname), ctype); - TREE_OPERAND (decl, 0) = NULL_TREE; - } - else - { - ctype = IDENTIFIER_TYPE_VALUE (cname); - TREE_OPERAND (decl, 0) = ctype; + my_friendly_assert (flags == NO_SPECIAL, 154); + flags = TYPENAME_FLAG; + ctor_return_type = TREE_TYPE (dname); + return_type = return_conversion; } + name = operator_name_string (dname); } + break; - if (ctype - && TREE_OPERAND (decl, 1) == constructor_name_full (ctype)) - TREE_OPERAND (decl, 1) = constructor_name (ctype); - decl = TREE_OPERAND (decl, 1); - if (ctype) + /* C++ extension */ + case SCOPE_REF: + { + /* Perform error checking, and decide on a ctype. */ + tree cname = TREE_OPERAND (decl, 0); + if (cname == NULL_TREE) + ctype = NULL_TREE; + else if (! is_aggr_type (cname, 1)) + TREE_OPERAND (decl, 0) = NULL_TREE; + /* Must test TREE_OPERAND (decl, 1), in case user gives + us `typedef (class::memfunc)(int); memfunc *memfuncptr;' */ + else if (TREE_OPERAND (decl, 1) + && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF) + ctype = cname; + else if (ctype == NULL_TREE) + ctype = cname; + else if (TREE_COMPLEXITY (decl) == current_class_depth) + TREE_OPERAND (decl, 0) = ctype; + else + { + if (! UNIQUELY_DERIVED_FROM_P (cname, ctype)) + { + cp_error ("type `%T' is not derived from type `%T'", + cname, ctype); + TREE_OPERAND (decl, 0) = NULL_TREE; + } + else + ctype = cname; + } + + if (ctype + && TREE_OPERAND (decl, 1) == constructor_name_full (ctype)) + TREE_OPERAND (decl, 1) = constructor_name (ctype); + next = &TREE_OPERAND (decl, 1); + decl = *next; + if (ctype) + { + if (TREE_CODE (decl) == IDENTIFIER_NODE + && constructor_name (ctype) == decl) + { + return_type = return_ctor; + ctor_return_type = ctype; + } + else if (TREE_CODE (decl) == BIT_NOT_EXPR + && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE + && (constructor_name (ctype) == TREE_OPERAND (decl, 0) + || constructor_name_full (ctype) == TREE_OPERAND (decl, 0))) + { + return_type = return_dtor; + ctor_return_type = ctype; + flags = DTOR_FLAG; + TREE_OPERAND (decl, 0) = constructor_name (ctype); + next = &TREE_OPERAND (decl, 0); + } + } + } + break; + + case ERROR_MARK: + next = 0; + break; + + default: + if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't') { - if (TREE_CODE (decl) == IDENTIFIER_NODE - && constructor_name (ctype) == decl) - { - return_type = return_ctor; - ctor_return_type = ctype; - } - else if (TREE_CODE (decl) == BIT_NOT_EXPR - && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE - && (constructor_name (ctype) == TREE_OPERAND (decl, 0) - || constructor_name_full (ctype) == TREE_OPERAND (decl, 0))) - { - return_type = return_dtor; - ctor_return_type = ctype; - flags = DTOR_FLAG; - decl = TREE_OPERAND (decl, 0) = constructor_name (ctype); - } + /* Parse error puts this typespec where + a declarator should go. */ + error ("typename specified as declarator-id"); + if (current_class_type) + cp_error (" perhaps you want `%T' for a constructor", + current_class_name); + dname = TYPE_IDENTIFIER (decl); + name = dname ? IDENTIFIER_POINTER (dname) : "<nameless>"; + declspecs = temp_tree_cons (NULL_TREE, integer_type_node, + declspecs); + *next = dname; + next = 0; + break; } + cp_compiler_error ("`%D' as declarator", decl); + return 0; /* We used to do a 155 abort here. */ } - break; - - case ERROR_MARK: - decl = NULL_TREE; - break; - - default: - return 0; /* We used to do a 155 abort here. */ - } + } if (name == NULL) name = "type name"; } @@ -10587,7 +10588,13 @@ xref_tag (code_type_node, name, binfo, globalize) /* If a cross reference is requested, look up the type already defined for this tag and return it. */ - t = IDENTIFIER_TYPE_VALUE (name); + if (TREE_CODE_CLASS (TREE_CODE (name)) == 't') + { + t = name; + name = TYPE_NESTED_NAME (t); + } + else + t = IDENTIFIER_TYPE_VALUE (name); if (t && TREE_CODE (t) != code) t = NULL_TREE; @@ -10770,17 +10777,17 @@ xref_basetypes (code_type_node, name, ref, binfo) { /* The base of a derived struct is public by default. */ int via_public - = (TREE_PURPOSE (binfo) == (tree)access_public - || TREE_PURPOSE (binfo) == (tree)access_public_virtual + = (TREE_PURPOSE (binfo) == access_public_node + || TREE_PURPOSE (binfo) == access_public_virtual_node || (tag_code != class_type - && (TREE_PURPOSE (binfo) == (tree)access_default - || TREE_PURPOSE (binfo) == (tree)access_default_virtual))); - int via_protected = TREE_PURPOSE (binfo) == (tree)access_protected; + && (TREE_PURPOSE (binfo) == access_default_node + || TREE_PURPOSE (binfo) == access_default_virtual_node))); + int via_protected = TREE_PURPOSE (binfo) == access_protected_node; int via_virtual - = (TREE_PURPOSE (binfo) == (tree)access_private_virtual - || TREE_PURPOSE (binfo) == (tree)access_public_virtual - || TREE_PURPOSE (binfo) == (tree)access_default_virtual); - tree basetype = TREE_TYPE (TREE_VALUE (binfo)); + = (TREE_PURPOSE (binfo) == access_private_virtual_node + || TREE_PURPOSE (binfo) == access_public_virtual_node + || TREE_PURPOSE (binfo) == access_default_virtual_node); + tree basetype = TREE_VALUE (binfo); tree base_binfo; GNU_xref_hier (IDENTIFIER_POINTER (name), diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 117687a..03b8ff9 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -176,7 +176,7 @@ int warn_traditional; /* Nonzero means warn about sizeof(function) or addition/subtraction of function pointers. */ -int warn_pointer_arith; +int warn_pointer_arith = 1; /* Nonzero means warn for non-prototype function decls or non-prototyped defs without previous prototype. */ @@ -2026,7 +2026,9 @@ constructor_name_full (thing) { if (TREE_CODE (thing) == UNINSTANTIATED_P_TYPE) return DECL_NAME (UPT_TEMPLATE (thing)); - if (IS_AGGR_TYPE_CODE (TREE_CODE (thing))) + else if (TREE_CODE (thing) == TEMPLATE_TYPE_PARM) + thing = TYPE_NAME (thing); + else if (IS_AGGR_TYPE_CODE (TREE_CODE (thing))) { if (TYPE_WAS_ANONYMOUS (thing) && TYPE_HAS_CONSTRUCTOR (thing)) thing = DECL_NAME (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (thing), 0)); diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 38fcb35..09aebdb 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -155,7 +155,7 @@ exception_section () if (flag_pic) data_section (); else -#if defined(TARGET_POWERPC) /* are we on a __rs6000? */ +#if defined (TARGET_POWERPC) /* are we on a __rs6000? */ data_section (); #else readonly_data_section (); @@ -1012,6 +1012,10 @@ expand_start_catch_block (declspecs, declarator) return; } + /* Make sure we mark the catch param as used, otherwise we'll get + a warning about an unused ((anonymous)). */ + TREE_USED (decl) = 1; + /* Figure out the type that the initializer is. */ init_type = TREE_TYPE (decl); if (TREE_CODE (init_type) != REFERENCE_TYPE @@ -1167,7 +1171,8 @@ static void do_unwind (inner_throw_label) rtx inner_throw_label; { -#if defined(SPARC_STACK_ALIGN) /* was sparc */ +#if defined (SPARC_STACK_ALIGN) /* was sparc */ + /* This doesn't work for the flat model sparc, I bet. */ tree fcall; tree params; rtx return_val_rtx; @@ -1186,7 +1191,7 @@ do_unwind (inner_throw_label) easy_expand_asm ("restore"); emit_barrier (); #endif -#if defined(ARM_FRAME_RTX) /* was __arm */ +#if defined (ARM_FRAME_RTX) /* was __arm */ if (flag_omit_frame_pointer) sorry ("this implementation of exception handling requires a frame pointer"); @@ -1195,7 +1200,7 @@ do_unwind (inner_throw_label) emit_move_insn (hard_frame_pointer_rtx, gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -12))); #endif -#if defined(TARGET_88000) /* was m88k */ +#if defined (TARGET_88000) /* was m88k */ rtx temp_frame = frame_pointer_rtx; temp_frame = memory_address (Pmode, temp_frame); @@ -1218,17 +1223,18 @@ do_unwind (inner_throw_label) (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0)))); #endif #endif -#if !defined(TARGET_88000) && !defined(ARM_FRAME_RTX) && !defined(SPARC_STACK_ALIGN) +#if ! defined (TARGET_88000) && ! defined (ARM_FRAME_RTX) && ! defined (SPARC_STACK_ALIGN) tree fcall; tree params; rtx return_val_rtx; +#if 0 + /* I would like to do this here, but the move below doesn't seem to work. */ /* call to __builtin_return_address () */ params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE); fcall = build_function_call (BuiltinReturnAddress, params); return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0); -#if 0 - /* I would like to do this here, but doesn't seem to work. */ + emit_move_insn (return_val_rtx, inner_throw_label); /* So, for now, just pass throw label to stack unwinder. */ #endif @@ -1242,6 +1248,48 @@ do_unwind (inner_throw_label) } +/* Given the return address, compute the new pc to throw. This has to + work for the current frame of the current function, and the one + above it in the case of throw. */ +rtx +eh_outer_context (addr) + rtx addr; +{ +#if defined (ARM_FRAME_RTX) /* was __arm */ + /* On the ARM, '__builtin_return_address', must have 4 + subtracted from it. */ + emit_insn (gen_add2_insn (addr, GEN_INT (-4))); + + /* If we are generating code for an ARM2/ARM3 machine or for an ARM6 + in 26 bit mode, the condition codes must be masked out of the + return value, or else they will confuse BuiltinReturnAddress. + This does not apply to ARM6 and later processors when running in + 32 bit mode. */ + if (!TARGET_6) + emit_insn (gen_rtx (SET, Pmode, + addr, + gen_rtx (AND, Pmode, + addr, GEN_INT (0x03fffffc)))); +#else +#if ! defined (SPARC_STACK_ALIGN) /* was sparc */ +#if defined (TARGET_SNAKE) + /* On HPPA, the low order two bits hold the priviledge level, so we + must get rid of them. */ + emit_insn (gen_rtx (SET, Pmode, + addr, + gen_rtx (AND, Pmode, + addr, GEN_INT (0xfffffffc)))); +#endif + + /* On the SPARC, __builtin_return_address is already -8 or -12, no + need to subtract any more from it. */ + addr = plus_constant (addr, -1); +#endif +#endif + + return addr; +} + /* is called from expand_exception_blocks () to generate the code in a function to "throw" if anything in the function needs to perform a throw. @@ -1320,8 +1368,9 @@ expand_builtin_throw () emit_label (gotta_rethrow_it); /* call to __builtin_return_address () */ -#if defined(ARM_FRAME_RTX) /* was __arm */ -/* This replaces a 'call' to __builtin_return_address */ +#if defined (ARM_FRAME_RTX) /* was __arm */ + /* This should be moved into arm.h:RETURN_ADDR_RTX */ + /* This replaces a 'call' to __builtin_return_address */ return_val_rtx = gen_reg_rtx (Pmode); emit_move_insn (return_val_rtx, gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -4))); #else @@ -1336,28 +1385,10 @@ expand_builtin_throw () emit_jump_insn (gen_beq (gotta_call_terminate)); -#if defined(ARM_FRAME_RTX) /* was __arm */ - /* On the ARM, '__builtin_return_address', must have 4 - subtracted from it. */ - emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-4))); + return_val_rtx = eh_outer_context (return_val_rtx); - /* If we are generating code for an ARM2/ARM3 machine or for an ARM6 in 26 bit - mode, the condition codes must be masked out of the return value, or else - they will confuse BuiltinReturnAddress. This does not apply to ARM6 and - later processors when running in 32 bit mode. */ - if (!TARGET_6) - emit_insn (gen_rtx (SET, Pmode, return_val_rtx, gen_rtx (AND, Pmode, return_val_rtx, GEN_INT (0x03fffffc)))); -#else -#if !defined(SPARC_STACK_ALIGN) /* was sparc */ - /* On the SPARC, __builtin_return_address is already -8, no need to - subtract any more from it. */ - return_val_rtx = plus_constant (return_val_rtx, -1); -#endif -#endif - - /* yes it did */ - t = build_modify_expr (saved_pc, NOP_EXPR, make_tree (ptr_type_node, return_val_rtx)); - expand_expr (t, const0_rtx, VOIDmode, 0); + /* Yes it did. */ + emit_move_insn (DECL_RTL (saved_pc), return_val_rtx); do_unwind (gen_rtx (LABEL_REF, Pmode, top_of_loop)); emit_jump (top_of_loop); @@ -1700,6 +1731,9 @@ expand_throw (exp) } } + if (cleanup == empty_fndecl) + assemble_external (empty_fndecl); + e = build_modify_expr (saved_throw_type, NOP_EXPR, throw_type); expand_expr (e, const0_rtx, VOIDmode, 0); @@ -1823,11 +1857,9 @@ end_eh_unwinder (end) ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS, 0, hard_frame_pointer_rtx); return_val_rtx = copy_to_reg (ret_val); -#ifdef RETURN_ADDR_OFFSET - return_val_rtx = plus_constant (return_val_rtx, RETURN_ADDR_OFFSET-1); -#else - return_val_rtx = plus_constant (return_val_rtx, -1); -#endif + + return_val_rtx = eh_outer_context (return_val_rtx); + emit_move_insn (DECL_RTL (saved_pc), return_val_rtx); #ifdef JUMP_TO_THROW diff --git a/gcc/cp/gxxint.texi b/gcc/cp/gxxint.texi index 015a33c..36c25205 100644 --- a/gcc/cp/gxxint.texi +++ b/gcc/cp/gxxint.texi @@ -1217,24 +1217,25 @@ The below points out some things that work in g++'s exception handling. All completely constructed temps and local variables are cleaned up in all unwinded scopes. Completely constructed parts of partially constructed objects are cleaned up. This includes partially built -arrays. Exception specifications are now handled. +arrays. Exception specifications are now handled. Thrown objects are +now cleaned up all the time. The below points out some flaws in g++'s exception handling, as it now stands. Only exact type matching or reference matching of throw types works when --fno-rtti is used. Only works on a SPARC (like Suns), i386, arm and -rs6000 machines. Partial support is in for all other machines, but a -stack unwinder called __unwind_function has to be written, and added to -libgcc2 for them. See below for details on __unwind_function. Don't -expect exception handling to work right if you optimize, in fact the -compiler will probably core dump. RTL_EXPRs for EH cond variables for -&& and || exprs should probably be wrapped in UNSAVE_EXPRs, and -RTL_EXPRs tweaked so that they can be unsaved, and the UNSAVE_EXPR code -should be in the backend, or alternatively, UNSAVE_EXPR should be ripped -out and exactly one finalization allowed to be expanded by the backend. -I talked with kenner about this, and we have to allow multiple -expansions. +-fno-rtti is used. Only works on a SPARC (like Suns), i386, arm, +rs6000, Alpha and mips machines. Partial support is in for all other +machines, but a stack unwinder called __unwind_function has to be +written, and added to libgcc2 for them. See below for details on +__unwind_function. Don't expect exception handling to work right if you +optimize, in fact the compiler will probably core dump. RTL_EXPRs for +EH cond variables for && and || exprs should probably be wrapped in +UNSAVE_EXPRs, and RTL_EXPRs tweaked so that they can be unsaved, and the +UNSAVE_EXPR code should be in the backend, or alternatively, UNSAVE_EXPR +should be ripped out and exactly one finalization allowed to be expanded +by the backend. I talked with kenner about this, and we have to allow +multiple expansions. We only do pointer conversions on exception matching a la 15.3 p2 case 3: `A handler with type T, const T, T&, or const T& is a match for a @@ -1266,12 +1267,13 @@ build_exception_variant should sort the incoming list, so that it implements set compares, not exact list equality. Type smashing should smash exception specifications using set union. -Thrown objects are usually allocated on the heap, in the usual way, but -they are never deleted. They should be deleted by the catch clauses. -If one runs out of heap space, throwing an object will probably never -work. This could be relaxed some by passing an __in_chrg parameter to -track who has control over the exception object. Thrown objects are not -allocated on the heap when they are pointer to object types. +Thrown objects are usually allocated on the heap, in the usual way. If +one runs out of heap space, throwing an object will probably never work. +This could be relaxed some by passing an __in_chrg parameter to track +who has control over the exception object. Thrown objects are not +allocated on the heap when they are pointer to object types. We should +extend it so that all small (<4*sizeof(void*)) objects are stored +directly, instead of allocated on the heap. When the backend returns a value, it can create new exception regions that need protecting. The new region should rethrow the object in diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 2c795bb..e114414 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -371,10 +371,10 @@ sort_base_init (t, rbase_ptr, vbase_ptr) last = tree_cons (NULL_TREE, NULL_TREE, current_base_init_list); for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x)) { - tree basename = TREE_PURPOSE (x); + tree basetype = TREE_PURPOSE (x); tree binfo; - if (basename == NULL_TREE) + if (basetype == NULL_TREE) { /* Initializer for single base class. Must not use multiple inheritance or this is ambiguous. */ @@ -393,9 +393,9 @@ sort_base_init (t, rbase_ptr, vbase_ptr) } binfo = TREE_VEC_ELT (binfos, 0); } - else if (is_aggr_typedef (basename, 1)) + else if (is_aggr_type (basetype, 1)) { - binfo = binfo_or_else (IDENTIFIER_TYPE_VALUE (basename), t); + binfo = binfo_or_else (basetype, t); if (binfo == NULL_TREE) continue; @@ -420,8 +420,7 @@ sort_base_init (t, rbase_ptr, vbase_ptr) if (i < 0) { cp_error ("`%T' is not an immediate base class of `%T'", - IDENTIFIER_TYPE_VALUE (basename), - current_class_type); + basetype, current_class_type); continue; } } @@ -931,6 +930,12 @@ expand_member_init (exp, name, init) type = TYPE_MAIN_VARIANT (TREE_TYPE (exp)); + if (TREE_CODE_CLASS (TREE_CODE (name)) == 't') + { + basetype = name; + name = TYPE_IDENTIFIER (name); + } + if (name == NULL_TREE && IS_AGGR_TYPE (type)) switch (CLASSTYPE_N_BASECLASSES (type)) { @@ -958,7 +963,7 @@ expand_member_init (exp, name, init) if (init == void_type_node) init = NULL_TREE; - if (name == NULL_TREE || IDENTIFIER_HAS_TYPE_VALUE (name)) + if (name == NULL_TREE || basetype) { tree base_init; @@ -976,7 +981,6 @@ expand_member_init (exp, name, init) } else { - basetype = IDENTIFIER_TYPE_VALUE (name); if (basetype != type && ! binfo_member (basetype, TYPE_BINFO (type)) && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type))) @@ -984,32 +988,28 @@ expand_member_init (exp, name, init) if (IDENTIFIER_CLASS_VALUE (name)) goto try_member; if (TYPE_USES_VIRTUAL_BASECLASSES (type)) - error ("type `%s' is not an immediate or virtual basetype for `%s'", - IDENTIFIER_POINTER (name), - TYPE_NAME_STRING (type)); + cp_error ("type `%T' is not an immediate or virtual basetype for `%T'", + basetype, type); else - error ("type `%s' is not an immediate basetype for `%s'", - IDENTIFIER_POINTER (name), - TYPE_NAME_STRING (type)); + cp_error ("type `%T' is not an immediate basetype for `%T'", + basetype, type); return; } } - if (purpose_member (name, current_base_init_list)) + if (purpose_member (basetype, current_base_init_list)) { - error ("base class `%s' already initialized", - IDENTIFIER_POINTER (name)); + cp_error ("base class `%T' already initialized", basetype); return; } if (warn_reorder && current_member_init_list) { - warning ("base initializer for `%s'", IDENTIFIER_POINTER (name)); + cp_warning ("base initializer for `%T'", basetype); warning (" will be re-ordered to precede member initializations"); } - base_init = build_tree_list (name, init); - TREE_TYPE (base_init) = basetype; + base_init = build_tree_list (basetype, init); current_base_init_list = chainon (current_base_init_list, base_init); } else @@ -1024,12 +1024,11 @@ expand_member_init (exp, name, init) if (purpose_member (name, current_member_init_list)) { - error ("field `%s' already initialized", IDENTIFIER_POINTER (name)); + cp_error ("field `%D' already initialized", field); return; } member_init = build_tree_list (name, init); - TREE_TYPE (member_init) = TREE_TYPE (field); current_member_init_list = chainon (current_member_init_list, member_init); } return; @@ -1741,6 +1740,26 @@ is_aggr_typedef (name, or_else) return 1; } +/* Report an error if TYPE is not a user-defined, aggregate type. If + OR_ELSE is nonzero, give an error message. */ +int +is_aggr_type (type, or_else) + tree type; + int or_else; +{ + if (type == error_mark_node) + return 0; + + if (! IS_AGGR_TYPE (type) + && TREE_CODE (type) != TEMPLATE_TYPE_PARM) + { + if (or_else) + cp_error ("`%T' is not an aggregate type", type); + return 0; + } + return 1; +} + /* Like is_aggr_typedef, but returns typedef if successful. */ tree get_aggr_from_typedef (name, or_else) @@ -1788,13 +1807,13 @@ get_type_value (name) /* This code could just as well go in `class.c', but is placed here for modularity. */ -/* For an expression of the form CNAME :: NAME (PARMLIST), build +/* For an expression of the form TYPE :: NAME (PARMLIST), build the appropriate function call. */ tree -build_member_call (cname, name, parmlist) - tree cname, name, parmlist; +build_member_call (type, name, parmlist) + tree type, name, parmlist; { - tree type, t; + tree t; tree method_name = name; int dtor = 0; int dont_use_this = 0; @@ -1806,22 +1825,19 @@ build_member_call (cname, name, parmlist) dtor = 1; } - if (TREE_CODE (cname) == SCOPE_REF) - cname = resolve_scope_to_name (NULL_TREE, cname); - /* This shouldn't be here, and build_member_call shouldn't appear in parse.y! (mrs) */ - if (cname && get_aggr_from_typedef (cname, 0) == 0 - && TREE_CODE (cname) == IDENTIFIER_NODE) + if (type && TREE_CODE (type) == IDENTIFIER_NODE + && get_aggr_from_typedef (type, 0) == 0) { - tree ns = lookup_name (cname, 0); + tree ns = lookup_name (type, 0); if (ns && TREE_CODE (ns) == NAMESPACE_DECL) { - return build_x_function_call (build_offset_ref (cname, name), parmlist, current_class_decl); + return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_decl); } } - if (cname == NULL_TREE || ! (type = get_aggr_from_typedef (cname, 1))) + if (type == NULL_TREE || ! is_aggr_type (type, 1)) return error_mark_node; /* An operator we did not like. */ @@ -1914,29 +1930,26 @@ build_member_call (cname, name, parmlist) /* Build a reference to a member of an aggregate. This is not a C++ `&', but really something which can have its address taken, - and then act as a pointer to member, for example CNAME :: FIELD - can have its address taken by saying & CNAME :: FIELD. + and then act as a pointer to member, for example TYPE :: FIELD + can have its address taken by saying & TYPE :: FIELD. @@ Prints out lousy diagnostics for operator <typename> @@ fields. @@ This function should be rewritten and placed in search.c. */ tree -build_offset_ref (cname, name) - tree cname, name; +build_offset_ref (type, name) + tree type, name; { - tree decl, type, fnfields, fields, t = error_mark_node; + tree decl, fnfields, fields, t = error_mark_node; tree basetypes = NULL_TREE; int dtor = 0; - if (TREE_CODE (cname) == SCOPE_REF) - cname = resolve_scope_to_name (NULL_TREE, cname); - /* Handle namespace names fully here. */ - if (TREE_CODE (cname) == IDENTIFIER_NODE - && get_aggr_from_typedef (cname, 0) == 0) + if (TREE_CODE (type) == IDENTIFIER_NODE + && get_aggr_from_typedef (type, 0) == 0) { - tree ns = lookup_name (cname, 0); + tree ns = lookup_name (type, 0); tree val; if (ns && TREE_CODE (ns) == NAMESPACE_DECL) { @@ -1948,17 +1961,18 @@ build_offset_ref (cname, name) } } - if (cname == NULL_TREE || ! is_aggr_typedef (cname, 1)) + if (type == NULL_TREE || ! is_aggr_type (type, 1)) return error_mark_node; - type = IDENTIFIER_TYPE_VALUE (cname); - if (TREE_CODE (name) == BIT_NOT_EXPR) { dtor = 1; name = TREE_OPERAND (name, 0); } + if (name == constructor_name_full (type)) + name = constructor_name (type); + if (TYPE_SIZE (type) == 0) { t = IDENTIFIER_CLASS_VALUE (name); @@ -1983,24 +1997,14 @@ build_offset_ref (cname, name) return error_mark_node; } -#if 0 - if (TREE_CODE (name) == TYPE_EXPR) - /* Pass a TYPE_DECL to build_component_type_expr. */ - return build_component_type_expr (TYPE_NAME (TREE_TYPE (cname)), - name, NULL_TREE, 1); -#endif - if (current_class_type == 0 || get_base_distance (type, current_class_type, 0, &basetypes) == -1) { basetypes = TYPE_BINFO (type); - decl = build1 (NOP_EXPR, - IDENTIFIER_TYPE_VALUE (cname), - error_mark_node); + decl = build1 (NOP_EXPR, type, error_mark_node); } else if (current_class_decl == 0) - decl = build1 (NOP_EXPR, IDENTIFIER_TYPE_VALUE (cname), - error_mark_node); + decl = build1 (NOP_EXPR, type, error_mark_node); else decl = C_C_D; @@ -2044,18 +2048,18 @@ build_offset_ref (cname, name) if (DECL_CHAIN (t) == NULL_TREE || dtor) { - enum access_type access; + tree access; /* unique functions are handled easily. */ unique: access = compute_access (basetypes, t); - if (access == access_protected) + if (access == access_protected_node) { cp_error_at ("member function `%#D' is protected", t); error ("in this context"); return error_mark_node; } - if (access == access_private) + if (access == access_private_node) { cp_error_at ("member function `%#D' is private", t); error ("in this context"); @@ -2066,7 +2070,7 @@ build_offset_ref (cname, name) } /* overloaded functions may need more work. */ - if (cname == name) + if (name == constructor_name (type)) { if (TYPE_HAS_DESTRUCTOR (type) && DECL_CHAIN (DECL_CHAIN (t)) == NULL_TREE) @@ -2134,11 +2138,13 @@ build_offset_ref (cname, name) } /* static class functions too. */ - if (TREE_CODE (t) == FUNCTION_DECL && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) + if (TREE_CODE (t) == FUNCTION_DECL + && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) my_friendly_abort (53); - /* In member functions, the form `cname::name' is no longer - equivalent to `this->cname::name'. */ + /* In member functions, the form `type::name' is no longer + equivalent to `this->type::name', at least not until + resolve_offset_ref. */ return build (OFFSET_REF, build_offset_type (type, TREE_TYPE (t)), decl, t); } @@ -2271,8 +2277,7 @@ resolve_offset_ref (exp) || (TREE_CODE (base) == NOP_EXPR && TREE_OPERAND (base, 0) == error_mark_node))) { - tree basetype_path; - enum access_type access; + tree basetype_path, access; if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE) basetype = TYPE_OFFSET_BASETYPE (type); @@ -2288,16 +2293,16 @@ resolve_offset_ref (exp) } addr = convert_pointer_to (basetype, base); access = compute_access (basetype_path, member); - if (access == access_public) + if (access == access_public_node) return build (COMPONENT_REF, TREE_TYPE (member), build_indirect_ref (addr, NULL_PTR), member); - if (access == access_protected) + if (access == access_protected_node) { cp_error_at ("member `%D' is protected", member); error ("in this context"); return error_mark_node; } - if (access == access_private) + if (access == access_private_node) { cp_error_at ("member `%D' is private", member); error ("in this context"); @@ -3928,15 +3933,15 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) if (flags & LOOKUP_PROTECT) { - enum access_type access = compute_access (basetypes, dtor); + tree access = compute_access (basetypes, dtor); - if (access == access_private) + if (access == access_private_node) { if (flags & LOOKUP_COMPLAIN) cp_error ("destructor for type `%T' is private in this scope", type); return error_mark_node; } - else if (access == access_protected) + else if (access == access_protected_node) { if (flags & LOOKUP_COMPLAIN) cp_error ("destructor for type `%T' is protected in this scope", type); diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 7795933..abab8fb 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -3018,9 +3018,8 @@ do_identifier (token) if (IDENTIFIER_CLASS_VALUE (token) == id) { /* Check access. */ - enum access_type access - = compute_access (TYPE_BINFO (current_class_type), id); - if (access == access_private) + tree access = compute_access (TYPE_BINFO (current_class_type), id); + if (access == access_private_node) cp_error ("enum `%D' is private", id); /* protected is OK, since it's an enum of `this'. */ } @@ -3279,13 +3278,13 @@ real_yylex () switch (ptr->rid) { case RID_PUBLIC: - yylval.itype = access_public; + yylval.ttype = access_public_node; break; case RID_PRIVATE: - yylval.itype = access_private; + yylval.ttype = access_private_node; break; case RID_PROTECTED: - yylval.itype = access_protected; + yylval.ttype = access_protected_node; break; default: my_friendly_abort (63); @@ -4394,6 +4393,13 @@ done: return value; } +int +is_rid (t) + tree t; +{ + return !!is_reserved_word (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t)); +} + typedef enum { d_kind, t_kind, s_kind, r_kind, e_kind, c_kind, diff --git a/gcc/cp/method.c b/gcc/cp/method.c index d50ea90..7e41536 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1582,8 +1582,7 @@ hack_identifier (value, name, yychar) if (DECL_LANG_SPECIFIC (value) && DECL_CLASS_CONTEXT (value) != current_class_type) { - tree path; - enum access_type access; + tree path, access; register tree context = (TREE_CODE (value) == FUNCTION_DECL && DECL_VIRTUAL_P (value)) ? DECL_CLASS_CONTEXT (value) @@ -1593,7 +1592,7 @@ hack_identifier (value, name, yychar) if (path) { access = compute_access (path, value); - if (access != access_public) + if (access != access_public_node) { if (TREE_CODE (value) == VAR_DECL) error ("static member `%s' is %s", @@ -2101,7 +2100,7 @@ do_build_copy_constructor (fndecl) (build_reference_type (basetype), parm, CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); p = convert_from_reference (p); - current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype), + current_base_init_list = tree_cons (basetype, p, current_base_init_list); } @@ -2116,7 +2115,7 @@ do_build_copy_constructor (fndecl) (build_reference_type (basetype), parm, CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); p = convert_from_reference (p); - current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype), + current_base_init_list = tree_cons (basetype, p, current_base_init_list); } for (; fields; fields = TREE_CHAIN (fields)) @@ -2192,8 +2191,7 @@ do_build_assign_ref (fndecl) (build_reference_type (basetype), parm, CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); p = convert_from_reference (p); - p = build_member_call (TYPE_NESTED_NAME (basetype), - ansi_opname [MODIFY_EXPR], + p = build_member_call (basetype, ansi_opname [MODIFY_EXPR], build_tree_list (NULL_TREE, p)); expand_expr_stmt (p); } diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index d36624a..e3c2607 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -140,7 +140,7 @@ empty_parms () /* the reserved words... C++ extensions */ %token <ttype> AGGR -%token <itype> VISSPEC +%token <ttype> VISSPEC %token DELETE NEW OVERLOAD THIS OPERATOR CXX_TRUE CXX_FALSE %token NAMESPACE TYPENAME_KEYWORD USING %token LEFT_RIGHT TEMPLATE @@ -236,7 +236,7 @@ empty_parms () %type <ttype> named_complex_class_head_sans_basetype %type <ttype> unnamed_class_head %type <ttype> class_head base_class_list -%type <itype> base_class_access_list +%type <ttype> base_class_access_list %type <ttype> base_class maybe_base_class_list base_class.1 %type <ttype> exception_specification_opt ansi_raise_identifier ansi_raise_identifiers %type <ttype> operator_name @@ -779,13 +779,13 @@ member_init: '(' nonnull_exprlist ')' expand_member_init (C_C_D, NULL_TREE, void_type_node); } | notype_identifier '(' nonnull_exprlist ')' - { expand_member_init (C_C_D, $<ttype>$, $3); } + { expand_member_init (C_C_D, $1, $3); } | notype_identifier LEFT_RIGHT - { expand_member_init (C_C_D, $<ttype>$, void_type_node); } + { expand_member_init (C_C_D, $1, void_type_node); } | complete_type_name '(' nonnull_exprlist ')' - { expand_member_init (C_C_D, $<ttype>$, $3); } + { expand_member_init (C_C_D, $1, $3); } | complete_type_name LEFT_RIGHT - { expand_member_init (C_C_D, $<ttype>$, void_type_node); } + { expand_member_init (C_C_D, $1, void_type_node); } /* GNU extension */ | notype_qualified_id '(' nonnull_exprlist ')' { @@ -1589,7 +1589,7 @@ primary: | object overqualified_id '(' nonnull_exprlist ')' { got_object = NULL_TREE; - if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2)))) + if (IS_SIGNATURE (OP0 ($2))) { warning ("signature name in scope resolution ignored"); $$ = build_method_call ($$, OP1 ($2), $4, NULL_TREE, @@ -1601,7 +1601,7 @@ primary: | object overqualified_id LEFT_RIGHT { got_object = NULL_TREE; - if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2)))) + if (IS_SIGNATURE (OP0 ($2))) { warning ("signature name in scope resolution ignored"); $$ = build_method_call ($$, OP1 ($2), NULL_TREE, NULL_TREE, @@ -2349,9 +2349,8 @@ base_class_list: base_class: base_class.1 { - tree type; - type = IDENTIFIER_TYPE_VALUE ($$); - if (! is_aggr_typedef ($$, 1)) + tree type = $1; + if (! is_aggr_type (type, 1)) $$ = NULL_TREE; else if (current_aggr == signature_type_node && (! type) && (! IS_SIGNATURE (type))) @@ -2363,7 +2362,7 @@ base_class: { sorry ("signature inheritance, base type `%s' ignored", IDENTIFIER_POINTER ($$)); - $$ = build_tree_list ((tree)access_public, $$); + $$ = build_tree_list (access_public_node, $$); } else if (type && IS_SIGNATURE (type)) { @@ -2371,15 +2370,14 @@ base_class: $$ = NULL_TREE; } else - $$ = build_tree_list ((tree)access_default, $$); + $$ = build_tree_list (access_default_node, $$); } | base_class_access_list see_typename base_class.1 { - tree type; - type = IDENTIFIER_TYPE_VALUE ($3); + tree type = $3; if (current_aggr == signature_type_node) error ("access and source specifiers not allowed in signature"); - if (! is_aggr_typedef ($3, 1)) + if (! IS_AGGR_TYPE (type)) $$ = NULL_TREE; else if (current_aggr == signature_type_node && (! type) && (! IS_SIGNATURE (type))) @@ -2391,7 +2389,7 @@ base_class: { sorry ("signature inheritance, base type `%s' ignored", IDENTIFIER_POINTER ($$)); - $$ = build_tree_list ((tree)access_public, $3); + $$ = build_tree_list (access_public_node, $3); } else if (type && IS_SIGNATURE (type)) { @@ -2399,7 +2397,7 @@ base_class: $$ = NULL_TREE; } else - $$ = build_tree_list ((tree) $$, $3); + $$ = build_tree_list ($$, $3); } ; @@ -2412,8 +2410,7 @@ base_class.1: if (IS_AGGR_TYPE (TREE_TYPE ($3))) { sorry ("`sigof' as base signature specifier"); - /* need to return some dummy signature identifier */ - $$ = $3; + $$ = TREE_TYPE ($3); } else { @@ -2434,8 +2431,7 @@ base_class.1: if (IS_AGGR_TYPE (groktypename ($3))) { sorry ("`sigof' as base signature specifier"); - /* need to return some dummy signature identifier */ - $$ = $3; + $$ = groktypename ($3); } else { @@ -2456,40 +2452,40 @@ base_class_access_list: | SCSPEC see_typename { if ($<ttype>$ != ridpointers[(int)RID_VIRTUAL]) sorry ("non-virtual access"); - $$ = access_default_virtual; } + $$ = access_default_virtual_node; } | base_class_access_list VISSPEC see_typename { int err = 0; - if ($2 == access_protected) + if ($2 == access_protected_node) { warning ("`protected' access not implemented"); - $2 = access_public; + $2 = access_public_node; err++; } - else if ($2 == access_public) + else if ($2 == access_public_node) { - if ($1 == access_private) + if ($1 == access_private_node) { mixed: error ("base class cannot be public and private"); } - else if ($1 == access_default_virtual) - $$ = access_public_virtual; + else if ($1 == access_default_virtual_node) + $$ = access_public_virtual_node; } - else /* $2 == access_private */ + else /* $2 == access_private_node */ { - if ($1 == access_public) + if ($1 == access_public_node) goto mixed; - else if ($1 == access_default_virtual) - $$ = access_private_virtual; + else if ($1 == access_default_virtual_node) + $$ = access_private_virtual_node; } } | base_class_access_list SCSPEC see_typename { if ($2 != ridpointers[(int)RID_VIRTUAL]) sorry ("non-virtual access"); - if ($$ == access_public) - $$ = access_public_virtual; - else if ($$ == access_private) - $$ = access_private_virtual; } + if ($$ == access_public_node) + $$ = access_public_virtual_node; + else if ($$ == access_private_node) + $$ = access_private_virtual_node; } ; left_curly: '{' @@ -2564,18 +2560,18 @@ opt.component_decl_list: | component_decl_list { if (current_aggr == signature_type_node) - $$ = build_tree_list ((tree) access_public, $$); + $$ = build_tree_list (access_public_node, $$); else - $$ = build_tree_list ((tree) access_default, $$); + $$ = build_tree_list (access_default_node, $$); } | opt.component_decl_list VISSPEC ':' component_decl_list { - tree visspec = (tree) $2; + tree visspec = $2; if (current_aggr == signature_type_node) { error ("access specifier not allowed in signature"); - visspec = (tree) access_public; + visspec = access_public_node; } $$ = chainon ($$, build_tree_list (visspec, $4)); } @@ -2861,23 +2857,20 @@ after_type_declarator: qualified_type_name: type_name %prec EMPTY { + $$ = TREE_TYPE ($1); /* Remember that this name has been used in the class definition, as per [class.scope0] */ if (current_class_type && TYPE_BEING_DEFINED (current_class_type) - && ! IDENTIFIER_CLASS_VALUE ($$)) - { - tree t = lookup_name ($$, -2); - if (t) - pushdecl_class_level (t); - } + && ! IDENTIFIER_CLASS_VALUE ($1)) + pushdecl_class_level (lookup_name ($1, -2)); } | nested_type ; nested_type: nested_name_specifier type_name %prec EMPTY - { $$ = $2; } + { $$ = TREE_TYPE ($2); } ; direct_after_type_declarator: @@ -2941,9 +2934,9 @@ complex_direct_notype_declarator: | direct_notype_declarator '[' ']' { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); } | notype_qualified_id - { if (TREE_TYPE (OP0 ($$)) != current_class_type) + { if (OP0 ($$) != current_class_type) { - push_nested_class (TREE_TYPE (OP0 ($$)), 3); + push_nested_class (OP0 ($$), 3); TREE_COMPLEXITY ($$) = current_class_depth; } } @@ -2991,11 +2984,11 @@ nested_name_specifier: inline here?!? (jason) */ nested_name_specifier_1: TYPENAME SCOPE - { got_scope = TREE_TYPE ($$); } + { got_scope = $$ = TREE_TYPE ($1); } | NSNAME SCOPE - { got_scope = $$; } + { got_scope = $$ = $1; } | template_type SCOPE - { got_scope = TREE_TYPE ($$); } + { got_scope = $$ = TREE_TYPE ($1); } /* These break 'const i;' | IDENTIFIER SCOPE { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b80bff0..ffc7f33 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -127,13 +127,6 @@ process_template_parm (list, next) decl = build_decl (TYPE_DECL, TREE_VALUE (parm), t); TYPE_MAIN_DECL (t) = decl; parm = decl; - if (defval) - { - if (IDENTIFIER_HAS_TYPE_VALUE (defval)) - defval = IDENTIFIER_TYPE_VALUE (defval); - else - defval = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (defval)); - } } SET_DECL_ARTIFICIAL (decl); pushdecl (decl); diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 14b8d01..110eaed 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -794,23 +794,23 @@ current_scope () This will be static when lookup_fnfield comes into this file. - access_public means that the field can be accessed by the current lexical + access_public_node means that the field can be accessed by the current lexical scope. - access_protected means that the field cannot be accessed by the current + access_protected_node means that the field cannot be accessed by the current lexical scope because it is protected. - access_private means that the field cannot be accessed by the current + access_private_node means that the field cannot be accessed by the current lexical scope because it is private. */ #if 0 -#define PUBLIC_RETURN return (DECL_PUBLIC (field) = 1), access_public -#define PROTECTED_RETURN return (DECL_PROTECTED (field) = 1), access_protected -#define PRIVATE_RETURN return (DECL_PRIVATE (field) = 1), access_private +#define PUBLIC_RETURN return (DECL_PUBLIC (field) = 1), access_public_node +#define PROTECTED_RETURN return (DECL_PROTECTED (field) = 1), access_protected_node +#define PRIVATE_RETURN return (DECL_PRIVATE (field) = 1), access_private_node #else -#define PUBLIC_RETURN return access_public -#define PROTECTED_RETURN return access_protected -#define PRIVATE_RETURN return access_private +#define PUBLIC_RETURN return access_public_node +#define PROTECTED_RETURN return access_protected_node +#define PRIVATE_RETURN return access_private_node #endif #if 0 @@ -818,11 +818,11 @@ current_scope () static tree previous_scope = NULL_TREE; #endif -enum access_type +tree compute_access (basetype_path, field) tree basetype_path, field; { - enum access_type access; + tree access; tree types; tree context; int protected_ok, via_protected; @@ -836,11 +836,11 @@ compute_access (basetype_path, field) || (TREE_CODE (field) != FUNCTION_DECL && TREE_STATIC (field))); if (! flag_access_control) - return access_public; + return access_public_node; /* The field lives in the current class. */ if (BINFO_TYPE (basetype_path) == current_class_type) - return access_public; + return access_public_node; #if 0 /* Disabled until pushing function scope clears these out. If ever. */ @@ -848,17 +848,17 @@ compute_access (basetype_path, field) if (current_scope () == previous_scope) { if (DECL_PUBLIC (field)) - return access_public; + return access_public_node; if (DECL_PROTECTED (field)) - return access_protected; + return access_protected_node; if (DECL_PRIVATE (field)) - return access_private; + return access_private_node; } #endif /* We don't currently support access control on nested types. */ if (TREE_CODE (field) == TYPE_DECL) - return access_public; + return access_public_node; previous_scope = current_scope (); @@ -912,7 +912,7 @@ compute_access (basetype_path, field) basetype_path = reverse_path (basetype_path); types = basetype_path; via_protected = 0; - access = access_default; + access = access_default_node; protected_ok = static_mem && current_class_type && ACCESSIBLY_DERIVED_FROM_P (BINFO_TYPE (types), current_class_type); @@ -934,7 +934,7 @@ compute_access (basetype_path, field) member = purpose_member (type, DECL_ACCESS (field)); if (member) { - access = (enum access_type) TREE_VALUE (member); + access = TREE_VALUE (member); break; } @@ -948,7 +948,7 @@ compute_access (basetype_path, field) via_protected = 1; else if (! TREE_VIA_PUBLIC (types) && ! private_ok) { - access = access_private; + access = access_private_node; break; } } @@ -959,30 +959,30 @@ compute_access (basetype_path, field) /* No special visibilities apply. Use normal rules. */ - if (access == access_default) + if (access == access_default_node) { if (is_friend (context, previous_scope)) - access = access_public; + access = access_public_node; else if (TREE_PRIVATE (field)) - access = access_private; + access = access_private_node; else if (TREE_PROTECTED (field)) - access = access_protected; + access = access_protected_node; else - access = access_public; + access = access_public_node; } - if (access == access_public && via_protected) - access = access_protected; + if (access == access_public_node && via_protected) + access = access_protected_node; - if (access == access_protected && protected_ok) - access = access_public; + if (access == access_protected_node && protected_ok) + access = access_public_node; #if 0 - if (access == access_public) + if (access == access_public_node) DECL_PUBLIC (field) = 1; - else if (access == access_protected) + else if (access == access_protected_node) DECL_PROTECTED (field) = 1; - else if (access == access_private) + else if (access == access_private_node) DECL_PRIVATE (field) = 1; else my_friendly_abort (96); #endif @@ -1072,9 +1072,9 @@ lookup_field (xbasetype, name, protect, want_type) int head = 0, tail = 0; tree rval, rval_binfo = NULL_TREE, rval_binfo_h; tree type, basetype_chain, basetype_path; - enum access_type this_v = access_default; + tree this_v = access_default_node; tree entry, binfo, binfo_h; - enum access_type own_access = access_default; + tree own_access = access_default_node; int vbase_name_p = VBASE_NAME_P (name); /* rval_binfo is the binfo associated with the found member, note, @@ -1179,16 +1179,16 @@ lookup_field (xbasetype, name, protect, want_type) this_v = compute_access (basetype_path, rval); if (TREE_CODE (rval) == CONST_DECL) { - if (this_v == access_private) + if (this_v == access_private_node) errstr = "enum `%D' is a private value of class `%T'"; - else if (this_v == access_protected) + else if (this_v == access_protected_node) errstr = "enum `%D' is a protected value of class `%T'"; } else { - if (this_v == access_private) + if (this_v == access_private_node) errstr = "member `%D' is a private member of class `%T'"; - else if (this_v == access_protected) + else if (this_v == access_protected_node) errstr = "member `%D' is a protected member of class `%T'"; } } @@ -1370,14 +1370,14 @@ lookup_field (xbasetype, name, protect, want_type) /* If is possible for one of the derived types on the path to have defined special access for this field. Look for such declarations and report an error if a conflict is found. */ - enum access_type new_v; + tree new_v; - if (this_v != access_default) + if (this_v != access_default_node) new_v = compute_access (TREE_VALUE (TREE_CHAIN (*tp)), rval); - if (this_v != access_default && new_v != this_v) + if (this_v != access_default_node && new_v != this_v) { errstr = "conflicting access to member `%D'"; - this_v = access_default; + this_v = access_default_node; } own_access = new_v; CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp))); @@ -1397,15 +1397,15 @@ lookup_field (xbasetype, name, protect, want_type) if (errstr == 0) { - if (own_access == access_private) + if (own_access == access_private_node) errstr = "member `%D' declared private"; - else if (own_access == access_protected) + else if (own_access == access_protected_node) errstr = "member `%D' declared protected"; - else if (this_v == access_private) + else if (this_v == access_private_node) errstr = TREE_PRIVATE (rval) ? "member `%D' is private" : "member `%D' is from private base class"; - else if (this_v == access_protected) + else if (this_v == access_protected_node) errstr = TREE_PROTECTED (rval) ? "member `%D' is protected" : "member `%D' is from protected base class"; @@ -3334,10 +3334,14 @@ dfs_compress_decls (binfo) lattice. Where ambiguities result, we mark them with `error_mark_node' so that if they are encountered without explicit qualification, we can emit an error - message. */ + message. + + ONLY_TYPES is set when defining TYPE so that inherited types are visible + in the derived class. */ void -push_class_decls (type) +push_class_decls (type, only_types) tree type; + int only_types; { tree id; struct obstack *ambient_obstack = current_obstack; @@ -3392,7 +3396,12 @@ push_class_decls (type) /* Install the original class value in order to make pushdecl_class_level work correctly. */ IDENTIFIER_CLASS_VALUE (id) = TREE_VALUE (closed_envelopes); - if (TREE_CODE (new) == TREE_LIST) + if (only_types) + { + if (TREE_CODE (new) == TYPE_DECL) + set_identifier_type_value (id, TREE_TYPE (new)); + } + else if (TREE_CODE (new) == TREE_LIST) push_class_level_binding (id, new); else pushdecl_class_level (new); diff --git a/gcc/cp/sig.c b/gcc/cp/sig.c index 0337ce3..27d4e2e 100644 --- a/gcc/cp/sig.c +++ b/gcc/cp/sig.c @@ -530,7 +530,7 @@ build_signature_table_constructor (sig_ty, rhs) if (rhs_method == NULL_TREE || (compute_access (basetypes, rhs_method) - != access_public)) + != access_public_node)) { error ("class `%s' does not contain a method conforming to `%s'", TYPE_NAME_STRING (rhstype), diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 7fb688e..be0fc99 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -820,8 +820,8 @@ layout_basetypes (rec, binfos) goto got_it; } sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (basetype)); - decl = build_lang_decl (FIELD_DECL, get_identifier (name), - build_pointer_type (basetype)); + decl = build_lang_field_decl (FIELD_DECL, get_identifier (name), + build_pointer_type (basetype)); /* If you change any of the below, take a look at all the other VFIELD_BASEs and VTABLE_BASEs in the code, and change them too. */ @@ -1137,7 +1137,8 @@ get_decl_list (value) if (TREE_CODE (value) == IDENTIFIER_NODE) list = get_identifier_list (value); else if (TREE_CODE (value) == RECORD_TYPE - && TYPE_LANG_SPECIFIC (value)) + && TYPE_LANG_SPECIFIC (value) + && value == TYPE_MAIN_VARIANT (value)) list = CLASSTYPE_AS_LIST (value); if (list != NULL_TREE) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 3cb6d79..9901080 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1532,15 +1532,14 @@ build_object_ref (datum, basetype, field) basetype, field, dtype); return error_mark_node; } - else if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (basetype))) + else if (IS_SIGNATURE (basetype)) { warning ("signature name in scope resolution ignored"); return build_component_ref (datum, field, NULL_TREE, 1); } - else if (is_aggr_typedef (basetype, 1)) + else if (is_aggr_type (basetype, 1)) { - tree real_basetype = IDENTIFIER_TYPE_VALUE (basetype); - tree binfo = binfo_or_else (real_basetype, TREE_TYPE (datum)); + tree binfo = binfo_or_else (basetype, TREE_TYPE (datum)); if (binfo) return build_component_ref (build_scoped_ref (datum, basetype), field, binfo, 1); @@ -1590,15 +1589,14 @@ build_component_ref_1 (datum, field, protect) if (datum == C_C_D) { - enum access_type access - = compute_access (TYPE_BINFO (current_class_type), field); + tree access = compute_access (TYPE_BINFO (current_class_type), field); - if (access == access_private) + if (access == access_private_node) { cp_error ("field `%D' is private", field); return error_mark_node; } - else if (access == access_protected) + else if (access == access_protected_node) { cp_error ("field `%D' is protected", field); return error_mark_node; @@ -1748,14 +1746,13 @@ build_component_ref (datum, component, basetype_path, protect) if (TREE_CHAIN (fndecls) == NULL_TREE && DECL_CHAIN (TREE_VALUE (fndecls)) == NULL_TREE) { - enum access_type access; - tree fndecl; + tree access, fndecl; /* Unique, so use this one now. */ basetype = TREE_PURPOSE (fndecls); fndecl = TREE_VALUE (fndecls); access = compute_access (TREE_PURPOSE (fndecls), fndecl); - if (access == access_public) + if (access == access_public_node) { if (DECL_VINDEX (fndecl) && ! resolves_to_fixed_type_p (datum, 0)) @@ -1769,7 +1766,7 @@ build_component_ref (datum, component, basetype_path, protect) mark_used (fndecl); return fndecl; } - if (access == access_protected) + if (access == access_protected_node) cp_error ("member function `%D' is protected", fndecl); else cp_error ("member function `%D' is private", fndecl); @@ -3727,7 +3724,7 @@ pointer_int_sum (resultcode, ptrop, intop) } else if (TREE_CODE (TREE_TYPE (result_type)) == OFFSET_TYPE) { - if (pedantic) + if (pedantic || warn_pointer_arith) pedwarn ("ANSI C++ forbids using pointer to a member in arithmetic"); size_exp = integer_one_node; } @@ -3793,7 +3790,7 @@ pointer_diff (op0, op1) tree restype = ptrdiff_type_node; tree target_type = TREE_TYPE (TREE_TYPE (op0)); - if (pedantic) + if (pedantic || warn_pointer_arith) { if (TREE_CODE (target_type) == VOID_TYPE) pedwarn ("ANSI C++ forbids using pointer of type `void *' in subtraction"); @@ -6169,9 +6166,10 @@ build_modify_expr (lhs, modifycode, rhs) /* Can't initialize directly from a TARGET_EXPR, since that would cause the lhs to be constructed twice, and possibly result in accidental self-initialization. So we force the TARGET_EXPR to be - expanded. expand_expr should really do this by itself. */ + expanded without a target. */ if (TREE_CODE (newrhs) == TARGET_EXPR) - newrhs = expand_target_expr (newrhs); + newrhs = build (COMPOUND_EXPR, TREE_TYPE (newrhs), newrhs, + TREE_VALUE (newrhs)); } if (TREE_CODE (newrhs) == ERROR_MARK) diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 02ac42d..a2f8172 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1199,7 +1199,7 @@ process_init_constructor (type, init, elts) /* Given a structure or union value DATUM, construct and return the structure or union component which results from narrowing - that value by the types specified in TYPES. For example, given the + that value by the type specified in BASETYPE. For example, given the hierarchy class L { int ii; }; @@ -1213,23 +1213,16 @@ process_init_constructor (type, init, elts) then the expression - x::C::A::L::ii refers to the ii member of the L part of + x.A::ii refers to the ii member of the L part of of A part of the C object named by X. In this case, - DATUM would be x, and TYPES would be a SCOPE_REF consisting of - - SCOPE_REF - SCOPE_REF - C A - L - - The last entry in the SCOPE_REF is always an IDENTIFIER_NODE. + DATUM would be x, and BASETYPE would be A. */ tree -build_scoped_ref (datum, types) +build_scoped_ref (datum, basetype) tree datum; - tree types; + tree basetype; { tree ref; tree type = TREE_TYPE (datum); @@ -1242,62 +1235,17 @@ build_scoped_ref (datum, types) type = TYPE_MAIN_VARIANT (type); - if (TREE_CODE (types) == SCOPE_REF) - { - /* We have some work to do. */ - struct type_chain - { tree type; struct type_chain *next; } - *chain = NULL, *head = NULL, scratch; - ref = build_unary_op (ADDR_EXPR, datum, 0); - while (TREE_CODE (types) == SCOPE_REF) - { - tree t = TREE_OPERAND (types, 1); - if (is_aggr_typedef (t, 1)) - { - head = (struct type_chain *)alloca (sizeof (struct type_chain)); - head->type = IDENTIFIER_TYPE_VALUE (t); - head->next = chain; - chain = head; - types = TREE_OPERAND (types, 0); - } - else return error_mark_node; - } - if (! is_aggr_typedef (types, 1)) - return error_mark_node; - - head = &scratch; - head->type = IDENTIFIER_TYPE_VALUE (types); - head->next = chain; - chain = head; - while (chain) - { - tree binfo = chain->type; - type = TREE_TYPE (TREE_TYPE (ref)); - if (binfo != TYPE_BINFO (type)) - { - binfo = get_binfo (binfo, type, 1); - if (binfo == error_mark_node) - return error_mark_node; - if (binfo == 0) - return error_not_base_type (chain->type, type); - ref = convert_pointer_to (binfo, ref); - } - chain = chain->next; - } - return build_indirect_ref (ref, "(compiler error in build_scoped_ref)"); - } - /* This is an easy conversion. */ - if (is_aggr_typedef (types, 1)) + if (is_aggr_type (basetype, 1)) { - tree binfo = TYPE_BINFO (IDENTIFIER_TYPE_VALUE (types)); + tree binfo = TYPE_BINFO (basetype); if (binfo != TYPE_BINFO (type)) { binfo = get_binfo (binfo, type, 1); if (binfo == error_mark_node) return error_mark_node; if (binfo == 0) - return error_not_base_type (IDENTIFIER_TYPE_VALUE (types), type); + return error_not_base_type (basetype, type); } switch (TREE_CODE (datum)) |