From: Mike Stump Date: Fri, 15 Apr 1994 01:44:15 +0000 (+0000) Subject: 32nd Cygnus<->FSF merge X-Git-Tag: misc/cutover-egcs-0~6896 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a28e3c7f21098041386f8c52962ac75781849d95;p=thirdparty%2Fgcc.git 32nd Cygnus<->FSF merge From-SVN: r7047 --- diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in index 90d72f11eacc..9b5b508570b9 100644 --- a/gcc/cp/Makefile.in +++ b/gcc/cp/Makefile.in @@ -200,7 +200,7 @@ parse.o : $(srcdir)/parse.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h lex.h `echo $(srcdir)/parse.c | sed 's,^\./,,'` $(srcdir)/parse.c $(srcdir)/parse.h : $(srcdir)/parse.y - @echo expect 24 reduce/reduce conflicts. + @echo expect 33 reduce/reduce conflicts. cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 5a1e161c0085..261b16b24eab 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -2673,10 +2673,7 @@ build_scoped_method_call (exp, scopes, name, parms) { /* Explicit call to destructor. */ name = TREE_OPERAND (name, 0); - if (TREE_TYPE (decl) != - (IDENTIFIER_CLASS_VALUE (name) - ? IDENTIFIER_CLASS_TYPE_VALUE (name) - : IDENTIFIER_TYPE_VALUE (name))) + if (name != constructor_name (TREE_TYPE (decl))) { cp_error ("qualified type `%T' does not match destructor type `%T'", @@ -2808,6 +2805,10 @@ build_method_call (instance, name, parms, basetype_path, flags) /* If it doesn't work, two argument delete must work */ TREE_CHAIN (parms) = save_last; } + /* We already know whether it's needed or not for vec delete. */ + else if (name == ansi_opname[(int) VEC_DELETE_EXPR] + && ! TYPE_VEC_DELETE_TAKES_SIZE (TREE_TYPE (instance))) + TREE_CHAIN (parms) = NULL_TREE; if (TREE_CODE (name) == BIT_NOT_EXPR) { diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 20116fe25ade..b60cdec641f0 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2494,7 +2494,9 @@ finish_struct_methods (t, fn_fields, nonprivate_method) for (x = *testp; x; x = DECL_CHAIN (x)) { - if (DECL_NAME (fn_fields) == ansi_opname[(int) DELETE_EXPR]) + if (DECL_NAME (fn_fields) == ansi_opname[(int) DELETE_EXPR] + || DECL_NAME (fn_fields) + == ansi_opname[(int) VEC_DELETE_EXPR]) { /* ANSI C++ June 5 1992 WP 12.5.5.1 */ cp_error_at ("`%D' overloaded", fn_fields); @@ -4149,8 +4151,10 @@ finish_struct (t, list_of_fieldlists, warn_anon) else if (flag_dossier && ! CLASSTYPE_DOSSIER (t)) build_t_desc (t, 1); +#if 0 if (TYPE_NAME (t) && TYPE_IDENTIFIER (t)) undo_template_name_overload (TYPE_IDENTIFIER (t), 1); +#endif if (current_class_type) popclass (0); else @@ -4426,10 +4430,7 @@ pushclass (type, modify) current_function_decl = NULL_TREE; if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE) - { - declare_uninstantiated_type_level (); - overload_template_name (current_class_name, 0); - } + declare_uninstantiated_type_level (); else if (type != previous_class_type || current_class_depth > 1) { build_mi_matrix (type); @@ -4457,6 +4458,9 @@ pushclass (type, modify) unuse_fields (type); } + if (IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (type))) + overload_template_name (current_class_name, 0); + for (tags = CLASSTYPE_TAGS (type); tags; tags = TREE_CHAIN (tags)) { TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 1; @@ -4513,9 +4517,9 @@ popclass (modify) TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0; tags = TREE_CHAIN (tags); } + if (IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type))) + undo_template_name_overload (current_class_name, 0); } - if (TREE_CODE (current_class_type) == UNINSTANTIATED_P_TYPE) - undo_template_name_overload (current_class_name, 0); poplevel_class (); @@ -4583,7 +4587,12 @@ push_nested_class (type, modify) tree type; int modify; { - tree context = DECL_CONTEXT (TYPE_NAME (type)); + tree context; + + if (type == error_mark_node || ! IS_AGGR_TYPE (type)) + return; + + context = DECL_CONTEXT (TYPE_NAME (type)); if (context && TREE_CODE (context) == RECORD_TYPE) push_nested_class (context, 2); diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 3ddb359fcf74..4f73664f24a7 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -32,6 +32,7 @@ DEFTREECODE (CP_OFFSET_REF, "cp_offset_ref", "r", 2) Operand 1 is the value to pass to the destroying function saying whether the store should be deallocated as well. */ DEFTREECODE (DELETE_EXPR, "dl_expr", "e", 2) +DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", "e", 2) /* Value is reference to particular overloaded class method. Operand 0 is the class name (an IDENTIFIER_NODE); @@ -52,6 +53,7 @@ DEFTREECODE (TYPE_EXPR, "type_expr", "e", 1) operand 1 is argument list to initialization function, and operand 2 is the slot which was allocated for this expression. */ DEFTREECODE (NEW_EXPR, "nw_expr", "e", 3) +DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", "e", 3) /* Distinguish variables that are only used to identify exceptions that were caught. Only the DECL_NAME (and TREE_CHAIN) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e5a10db5b0f5..1fb1bb17da07 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -68,10 +68,6 @@ struct lang_id2 #define IDENTIFIER_TYPE_VALUE(NODE) (TREE_TYPE (NODE)) #define SET_IDENTIFIER_TYPE_VALUE(NODE,TYPE) (TREE_TYPE (NODE) = TYPE) #define IDENTIFIER_HAS_TYPE_VALUE(NODE) (TREE_TYPE (NODE) ? 1 : 0) -#define IDENTIFIER_HAS_CLASS_TYPE_VALUE(NODE) \ - (IDENTIFIER_CLASS_VALUE (NODE) && TREE_TYPE (IDENTIFIER_CLASS_VALUE (NODE))) -#define IDENTIFIER_CLASS_TYPE_VALUE(NODE) \ - TREE_TYPE (IDENTIFIER_CLASS_VALUE (NODE)) #define LANG_ID_FIELD(NAME,NODE) \ (((struct lang_identifier *)(NODE))->x \ @@ -325,7 +321,7 @@ enum languages { lang_c, lang_cplusplus }; #define TYPE_ASSEMBLER_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE)))) #define IS_AGGR_TYPE(t) (TYPE_LANG_FLAG_5 (t)) -#define IS_AGGR_TYPE_CODE(t) (t == RECORD_TYPE || t == UNION_TYPE) +#define IS_AGGR_TYPE_CODE(t) (t == RECORD_TYPE || t == UNION_TYPE || t == UNINSTANTIATED_P_TYPE) #define IS_AGGR_TYPE_2(TYPE1,TYPE2) \ (TREE_CODE (TYPE1) == TREE_CODE (TYPE2) \ && IS_AGGR_TYPE (TYPE1)&IS_AGGR_TYPE (TYPE2)) @@ -395,14 +391,13 @@ struct lang_type unsigned vtable_needs_writing : 1; unsigned has_assign_ref : 1; - unsigned gets_new : 1; - unsigned gets_placed_new : 1; - unsigned gets_delete : 1; + unsigned gets_new : 2; + unsigned gets_delete : 2; unsigned has_call_overloaded : 1; unsigned has_array_ref_overloaded : 1; unsigned has_arrow_overloaded : 1; - unsigned local_typedecls : 1; + unsigned local_typedecls : 1; unsigned interface_only : 1; unsigned interface_unknown : 1; unsigned needs_virtual_reinit : 1; @@ -410,16 +405,16 @@ struct lang_type unsigned declared_class : 1; unsigned being_defined : 1; unsigned redefined : 1; - unsigned no_globalize : 1; + unsigned no_globalize : 1; unsigned marked : 1; unsigned marked2 : 1; unsigned marked3 : 1; unsigned marked4 : 1; unsigned marked5 : 1; unsigned marked6 : 1; - unsigned use_template : 2; + unsigned use_template : 2; unsigned debug_requested : 1; unsigned has_method_call_overloaded : 1; unsigned private_attr : 1; @@ -427,8 +422,8 @@ struct lang_type unsigned ptrmemfunc_flag : 1; unsigned is_signature : 1; unsigned is_signature_pointer : 1; - unsigned is_signature_reference : 1; + unsigned is_signature_reference : 1; unsigned has_default_implementation : 1; unsigned grokking_typedef : 1; unsigned has_opaque_typedecls : 1; @@ -436,15 +431,16 @@ struct lang_type unsigned was_anonymous : 1; unsigned has_real_assignment : 1; unsigned has_real_assign_ref : 1; + unsigned has_const_init_ref : 1; - unsigned has_complex_init_ref : 1; unsigned has_complex_assign_ref : 1; + unsigned vec_delete_takes_size : 1; /* The MIPS compiler gets it wrong if this struct also does not fill out to a multiple of 4 bytes. Add a member `dummy' with new bits if you go over the edge. */ - unsigned dummy : 22; + unsigned dummy : 20; unsigned n_vancestors : 16; } type_flags; @@ -519,9 +515,17 @@ struct lang_type /* Nonzero for _CLASSTYPE means that operator new and delete are defined, respectively. */ -#define TREE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_new) -#define TREE_GETS_PLACED_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_placed_new) -#define TREE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_delete) +#define TYPE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_new) +#define TYPE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_delete) +#define TYPE_GETS_REG_DELETE(NODE) (TYPE_GETS_DELETE (NODE) & 1) + +/* Nonzero for _CLASSTYPE means that operator vec delete is defined and + takes the optional size_t argument. */ +#define TYPE_VEC_DELETE_TAKES_SIZE(NODE) \ + (TYPE_LANG_SPECIFIC(NODE)->type_flags.vec_delete_takes_size) +#define TYPE_VEC_NEW_USES_COOKIE(NODE) \ + (TYPE_NEEDS_DESTRUCTOR (NODE) \ + || (TYPE_LANG_SPECIFIC (NODE) && TYPE_VEC_DELETE_TAKES_SIZE (NODE))) /* Nonzero for TREE_LIST or _TYPE node means that this node is class-local. */ #define TREE_NONLOCAL_FLAG(NODE) (TREE_LANG_FLAG_0 (NODE)) @@ -1972,7 +1976,7 @@ extern tree expand_vec_init PROTO((tree, tree, tree, tree, int)); extern tree build_x_delete PROTO((tree, tree, int, tree)); extern tree build_delete PROTO((tree, tree, tree, int, int)); extern tree build_vbase_delete PROTO((tree, tree)); -extern tree build_vec_delete PROTO((tree, tree, tree, tree, tree, tree)); +extern tree build_vec_delete PROTO((tree, tree, tree, tree, tree, int)); /* in input.c */ @@ -2081,6 +2085,7 @@ extern int do_pending_expansions PROTO((void)); extern void do_pending_templates PROTO((void)); struct tinst_level *tinst_for_decl PROTO((void)); extern void do_function_instantiation PROTO((tree, tree)); +extern tree create_nested_upt PROTO((tree, tree)); /* in search.c */ extern tree make_memoized_table_entry PROTO((tree, tree, int)); @@ -2092,6 +2097,7 @@ extern enum access_type 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)); +extern tree lookup_nested_tag PROTO((tree, tree)); extern HOST_WIDE_INT breadth_first_search PROTO((tree, int (*)(), int (*)())); extern int tree_needs_constructor_p PROTO((tree, int)); extern int tree_has_any_destructor_p PROTO((tree, int)); @@ -2193,6 +2199,7 @@ extern int comp_target_types PROTO((tree, tree, int)); extern tree common_base_types PROTO((tree, tree)); extern int compparms PROTO((tree, tree, int)); extern int comp_target_types PROTO((tree, tree, int)); +extern int self_promoting_args_p PROTO((tree)); extern tree unsigned_type PROTO((tree)); extern tree signed_type PROTO((tree)); extern tree signed_or_unsigned_type PROTO((int, tree)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index fbe0d61a8650..d19354d33ae0 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -720,8 +720,16 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum, { /* When casting an lvalue to a reference type, just convert into a pointer to the new type and deference it. This is allowed - by San Diego WP section 5.2.8 paragraph 9, though perhaps it + by San Diego WP section 5.2.9 paragraph 12, though perhaps it should be done directly (jason). (int &)ri ---> *(int*)&ri */ + + /* B* bp; A& ar = (A&)bp; is legal, but it's probably not what they + meant. */ + if (form == POINTER_TYPE + && (comptypes (TREE_TYPE (intype), type, strict))) + cp_warning ("casting `%T' to `%T' does not dereference pointer", + intype, reftype); + rval = build_unary_op (ADDR_EXPR, expr, 0); if (rval != error_mark_node) rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval); @@ -744,6 +752,7 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum, /* Definitely need to go through a constructor here. */ if (TYPE_HAS_CONSTRUCTOR (type) + && ! CLASSTYPE_ABSTRACT_VIRTUALS (type) && (rval = build_method_call (NULL_TREE, constructor_name_full (type), build_tree_list (NULL_TREE, expr), TYPE_BINFO (type), diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 67812169a2e2..3dce83c650eb 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1964,7 +1964,8 @@ decls_match (newdecl, olddecl) { int types_match; - if (TREE_CODE (newdecl) == FUNCTION_DECL && TREE_CODE (olddecl) == FUNCTION_DECL) + if (TREE_CODE (newdecl) == FUNCTION_DECL + && TREE_CODE (olddecl) == FUNCTION_DECL) { tree f1 = TREE_TYPE (newdecl); tree f2 = TREE_TYPE (olddecl); @@ -1997,10 +1998,19 @@ decls_match (newdecl, olddecl) if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (f1)), TYPE_MAIN_VARIANT (TREE_TYPE (f2)), 2)) { - if (DECL_LANGUAGE (olddecl) == lang_c - && ! strict_prototypes_lang_c + if (! strict_prototypes_lang_c && DECL_LANGUAGE (olddecl) == lang_c && p2 == NULL_TREE) - types_match = self_promoting_args_p (p1); + { + types_match = self_promoting_args_p (p1); + if (p1 == void_list_node) + TREE_TYPE (newdecl) = TREE_TYPE (olddecl); + } + else if (!strict_prototypes_lang_c && DECL_LANGUAGE (olddecl)==lang_c + && DECL_LANGUAGE (newdecl) == lang_c && p1 == NULL_TREE) + { + types_match = self_promoting_args_p (p2); + TREE_TYPE (newdecl) = TREE_TYPE (olddecl); + } else types_match = compparms (p1, p2, 1); } @@ -2249,12 +2259,7 @@ duplicate_decls (newdecl, olddecl) int foo () { bar (); } is OK. */ if (current_lang_stack == current_lang_base) - { - DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl); - if (TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == NULL_TREE - && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) == void_list_node) - TREE_TYPE (newdecl) = TREE_TYPE (olddecl); - } + DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl); else { cp_error_at ("previous declaration of `%#D' with %L linkage", @@ -2268,7 +2273,8 @@ duplicate_decls (newdecl, olddecl) if (pedantic && (TREE_READONLY (newdecl) != TREE_READONLY (olddecl) || TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))) - cp_error_at ("type qualifiers for `%D' conflict with previous decl", newdecl); + cp_error_at ("type qualifiers for `%D' conflict with previous decl", + newdecl); } /* If new decl is `static' and an `extern' was seen previously, @@ -2318,7 +2324,8 @@ duplicate_decls (newdecl, olddecl) } Thing; */ #if 0 - my_friendly_assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl), 139); + my_friendly_assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl), + 139); #endif } @@ -2363,9 +2370,10 @@ duplicate_decls (newdecl, olddecl) TREE_TYPE (olddecl) = build_exception_variant (ctype, newtype, TYPE_RAISES_EXCEPTIONS (oldtype)); - if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE(olddecl), 0)) + if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0)) { - cp_error ("declaration of `%D' raises different exceptions...", newdecl); + cp_error ("declaration of `%D' raises different exceptions...", + newdecl); cp_error_at ("...from previous declaration here", olddecl); } } @@ -2683,7 +2691,8 @@ pushdecl (x) if (extra_warnings) { - cp_warning ("`static' missing from declaration of `%D'", t); + cp_warning ("`static' missing from declaration of `%D'", + t); warning_with_file_and_line (file, line, "previous declaration of `%s'", decl_as_string (t, 0)); @@ -3176,8 +3185,11 @@ push_overloaded_decl (decl, forgettable) { if (decl == tmp || duplicate_decls (decl, tmp)) return tmp; - if (compparms (TYPE_ARG_TYPES (TREE_TYPE (decl)), - TYPE_ARG_TYPES (TREE_TYPE (tmp)), 2)) + /* Avoid doing things about built-ins, since duplicate_decls + will have given warnings/errors for them. */ + if (!DECL_BUILT_IN (tmp) && !DECL_BUILT_IN_NONANSI (tmp) + && compparms (TYPE_ARG_TYPES (TREE_TYPE (decl)), + TYPE_ARG_TYPES (TREE_TYPE (tmp)), 2)) { cp_error ("new declaration `%#D'", decl); cp_error_at ("ambiguates old declaration `%#D'", tmp); @@ -3762,7 +3774,8 @@ lookup_nested_type (type, context) } break; case FUNCTION_DECL: - return TYPE_IDENTIFIER (type) ? lookup_name (TYPE_IDENTIFIER (type), 1) : NULL_TREE; + return TYPE_IDENTIFIER (type) ? + lookup_name (TYPE_IDENTIFIER (type), 1) : NULL_TREE; break; default: my_friendly_abort (12); @@ -3778,6 +3791,7 @@ lookup_nested_type (type, context) definitions if there are many, or return 0 if it is undefined. If PREFER_TYPE is > 0, we prefer TYPE_DECLs. + If PREFER_TYPE is -2, we're being called from yylex(). (UGLY) Otherwise we prefer non-TYPE_DECLs. */ tree @@ -3786,7 +3800,43 @@ lookup_name (name, prefer_type) int prefer_type; { register tree val; + int yylex = 0; + if (prefer_type == -2) + { + extern int looking_for_typename; + + yylex = 1; + prefer_type = looking_for_typename; + + if (got_scope != NULL_TREE) + { + if (got_scope == void_type_node) + val = IDENTIFIER_GLOBAL_VALUE (name); + else if (TREE_CODE (got_scope) == TEMPLATE_TYPE_PARM + /* TFIXME -- don't do this for UPTs in new model. */ + || TREE_CODE (got_scope) == UNINSTANTIATED_P_TYPE) + { + if (prefer_type > 0) + val = create_nested_upt (got_scope, name); + else + val = NULL_TREE; + } + else if (! IS_AGGR_TYPE (got_scope)) + /* Someone else will give an error about this if needed. */ + val = NULL_TREE; + else if (got_scope == current_class_type) + val = IDENTIFIER_CLASS_VALUE (name); + else if (TYPE_BEING_DEFINED (got_scope)) + val = lookup_nested_tag (got_scope, name); + else + val = lookup_field (got_scope, name, 0, 0); + + got_scope = NULL_TREE; + goto done; + } + } + if (current_binding_level != global_binding_level && IDENTIFIER_LOCAL_VALUE (name)) val = IDENTIFIER_LOCAL_VALUE (name); @@ -3802,7 +3852,7 @@ lookup_name (name, prefer_type) /* Try to find values from base classes if we are presently defining a type. We are presently only interested in TYPE_DECLs. */ - val = lookup_field (current_class_type, name, 0, prefer_type < 0); + val = lookup_field (current_class_type, name, 0, 1); if (val == error_mark_node) return val; if (val && TREE_CODE (val) != TYPE_DECL) @@ -3813,7 +3863,7 @@ lookup_name (name, prefer_type) the nested name at the point where we haven't even, for example, created the COMPONENT_REF or anything like that. */ if (val == NULL_TREE) - val = lookup_nested_field (name, prefer_type != -2); + val = lookup_nested_field (name, ! yylex); if (val == NULL_TREE) val = IDENTIFIER_GLOBAL_VALUE (name); @@ -3821,21 +3871,19 @@ lookup_name (name, prefer_type) else val = IDENTIFIER_GLOBAL_VALUE (name); + done: if (val) { - extern int looking_for_typename; - /* Arbitrate between finding a TYPE_DECL and finding other kinds of _DECLs. */ - if (TREE_CODE (val) == TYPE_DECL || looking_for_typename < 0) + if (TREE_CODE (val) == TYPE_DECL || prefer_type < 0) return val; if (IDENTIFIER_HAS_TYPE_VALUE (name)) { register tree val_as_type = TYPE_NAME (IDENTIFIER_TYPE_VALUE (name)); - if (val == val_as_type || prefer_type > 0 - || looking_for_typename > 0) + if (val == val_as_type || prefer_type > 0) return val_as_type; return val; @@ -4088,7 +4136,8 @@ init_decl_processing () error_mark_list = build_tree_list (error_mark_node, error_mark_node); TREE_TYPE (error_mark_list) = error_mark_node; - pushlevel (0); /* make the binding_level structure for global names. */ + /* Make the binding_level structure for global names. */ + pushlevel (0); global_binding_level = current_binding_level; this_identifier = get_identifier (THIS_NAME); @@ -4229,7 +4278,8 @@ init_decl_processing () TREE_TYPE (void_zero_node) = void_type_node; string_type_node = build_pointer_type (char_type_node); - const_string_type_node = build_pointer_type (build_type_variant (char_type_node, 1, 0)); + const_string_type_node = + build_pointer_type (build_type_variant (char_type_node, 1, 0)); record_builtin_type (RID_MAX, NULL_PTR, string_type_node); /* Make a type to be the domain of a few array types @@ -4257,7 +4307,8 @@ init_decl_processing () build_pointer_type (default_function_type); ptr_type_node = build_pointer_type (void_type_node); - const_ptr_type_node = build_pointer_type (build_type_variant (void_type_node, 1, 0)); + const_ptr_type_node = + build_pointer_type (build_type_variant (void_type_node, 1, 0)); record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node); endlink = void_list_node; int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink); @@ -4269,14 +4320,16 @@ init_decl_processing () double_ftype_double_double = build_function_type (double_type_node, - tree_cons (NULL_TREE, double_type_node, double_endlink)); + tree_cons (NULL_TREE, double_type_node, + double_endlink)); int_ftype_int = build_function_type (integer_type_node, int_endlink); long_ftype_long = build_function_type (long_integer_type_node, - tree_cons (NULL_TREE, long_integer_type_node, endlink)); + tree_cons (NULL_TREE, long_integer_type_node, + endlink)); void_ftype_ptr_ptr_int = build_function_type (void_type_node, @@ -4466,7 +4519,8 @@ init_decl_processing () builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP, NULL_PTR); builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, NULL_PTR); - builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, NULL_PTR); + builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, + NULL_PTR); #if 0 /* Not yet. */ builtin_function ("strncpy", strncpy_ftype, BUILT_IN_STRNCPY, NULL_PTR); @@ -4481,13 +4535,19 @@ init_decl_processing () or build_function_call. */ builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, 0); builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, 0); - builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR, 0); + builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR, + 0); builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL, 0); - builtin_function ("__builtin_fmod", double_ftype_double_double, BUILT_IN_FMOD, 0); - builtin_function ("__builtin_frem", double_ftype_double_double, BUILT_IN_FREM, 0); - builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, BUILT_IN_MEMSET, 0); - builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP, 0); - builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN, 0); + builtin_function ("__builtin_fmod", double_ftype_double_double, + BUILT_IN_FMOD, 0); + builtin_function ("__builtin_frem", double_ftype_double_double, + BUILT_IN_FREM, 0); + builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, BUILT_IN_MEMSET, + 0); + builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP, + 0); + builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN, + 0); #endif /* C++ extensions */ @@ -4507,7 +4567,7 @@ init_decl_processing () TYPE_MODE (unknown_type_node) = TYPE_MODE (void_type_node); /* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */ TREE_TYPE (unknown_type_node) = unknown_type_node; - /* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same result. */ + /* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same result. */ TYPE_POINTER_TO (unknown_type_node) = unknown_type_node; TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node; @@ -4544,9 +4604,12 @@ init_decl_processing () fields names so that the debugger can use them. */ memptr_type = make_lang_type (RECORD_TYPE); - fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, delta_type_node); - fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier, delta_type_node); - fields[2] = build_lang_field_decl (FIELD_DECL, pfn_identifier, ptr_type_node); + fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, + delta_type_node); + fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier, + delta_type_node); + fields[2] = build_lang_field_decl (FIELD_DECL, pfn_identifier, + ptr_type_node); finish_builtin_type (memptr_type, VTBL_PTR_TYPE, fields, 2, double_type_node); @@ -4588,9 +4651,15 @@ init_decl_processing () if (flag_handle_signatures) { sigtable_entry_type = make_lang_type (RECORD_TYPE); - fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier (SIGTABLE_CODE_NAME), short_integer_type_node); - fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier (SIGTABLE_OFFSET_NAME), short_integer_type_node); - fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier (SIGTABLE_PFN_NAME), ptr_type_node); + fields[0] = build_lang_field_decl (FIELD_DECL, + get_identifier (SIGTABLE_CODE_NAME), + short_integer_type_node); + fields[1] = build_lang_field_decl (FIELD_DECL, + get_identifier (SIGTABLE_OFFSET_NAME), + short_integer_type_node); + fields[2] = build_lang_field_decl (FIELD_DECL, + get_identifier (SIGTABLE_PFN_NAME), + ptr_type_node); finish_builtin_type (sigtable_entry_type, SIGTABLE_PTR_TYPE, fields, 2, double_type_node); sigtable_entry_type = build_type_variant (sigtable_entry_type, 1, 0); @@ -4620,9 +4689,12 @@ init_decl_processing () __t_desc_type_node = make_lang_type (RECORD_TYPE); __i_desc_type_node = make_lang_type (RECORD_TYPE); __m_desc_type_node = make_lang_type (RECORD_TYPE); - __t_desc_array_type = build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE); - __i_desc_array_type = build_array_type (TYPE_POINTER_TO (__i_desc_type_node), NULL_TREE); - __m_desc_array_type = build_array_type (TYPE_POINTER_TO (__m_desc_type_node), NULL_TREE); + __t_desc_array_type = + build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE); + __i_desc_array_type = + build_array_type (TYPE_POINTER_TO (__i_desc_type_node), NULL_TREE); + __m_desc_array_type = + build_array_type (TYPE_POINTER_TO (__m_desc_type_node), NULL_TREE); fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"), string_type_node); @@ -4630,7 +4702,8 @@ init_decl_processing () unsigned_type_node); fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("bits"), unsigned_type_node); - fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("points_to"), + fields[3] = build_lang_field_decl (FIELD_DECL, + get_identifier ("points_to"), TYPE_POINTER_TO (__t_desc_type_node)); fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("ivars_count"), @@ -4666,7 +4739,8 @@ init_decl_processing () integer_type_node); fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"), TYPE_POINTER_TO (__t_desc_type_node)); - finish_builtin_type (__i_desc_type_node, "__i_desc", fields, 2, integer_type_node); + finish_builtin_type (__i_desc_type_node, "__i_desc", fields, 2, + integer_type_node); /* method descriptors look like this: @@ -4699,7 +4773,8 @@ init_decl_processing () short_integer_type_node); fields[7] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_types"), build_pointer_type (build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE))); - finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7, integer_type_node); + finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7, + integer_type_node); } /* Now, C++. */ @@ -4720,11 +4795,21 @@ init_decl_processing () tree_cons (NULL_TREE, sizetype, void_list_node)), NOT_BUILT_IN); + auto_function (ansi_opname[(int) VEC_NEW_EXPR], + build_function_type (ptr_type_node, + tree_cons (NULL_TREE, sizetype, + void_list_node)), + NOT_BUILT_IN); auto_function (ansi_opname[(int) DELETE_EXPR], build_function_type (void_type_node, tree_cons (NULL_TREE, ptr_type_node, void_list_node)), NOT_BUILT_IN); + auto_function (ansi_opname[(int) VEC_DELETE_EXPR], + build_function_type (void_type_node, + tree_cons (NULL_TREE, ptr_type_node, + void_list_node)), + NOT_BUILT_IN); abort_fndecl = define_function ("abort", @@ -4889,7 +4974,8 @@ shadow_tag (declspecs) function members. */ if (TYPE_FIELDS (t)) { - tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0, NULL_TREE); + tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0, + NULL_TREE); finish_anon_union (decl); } else @@ -4982,7 +5068,8 @@ start_decl (declarator, declspecs, initialized, raises) /* This should only be done once on the top most decl. */ if (have_extern_spec && !used_extern_spec) { - declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), declspecs); + declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), + declspecs); used_extern_spec = 1; } @@ -5057,9 +5144,11 @@ start_decl (declarator, declspecs, initialized, raises) DECL_ARGUMENTS (decl) = args; } d = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), TREE_TYPE (decl)); - if (interface_unknown && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl)) + if (interface_unknown && flag_external_templates + && ! DECL_IN_SYSTEM_HEADER (decl)) warn_if_unknown_interface (); - TREE_PUBLIC (d) = TREE_PUBLIC (decl) = flag_external_templates && !interface_unknown; + TREE_PUBLIC (d) = TREE_PUBLIC (decl) = + flag_external_templates && !interface_unknown; TREE_STATIC (d) = TREE_STATIC (decl); DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl) && !(context && !DECL_THIS_EXTERN (decl))); @@ -5251,7 +5340,8 @@ start_decl (declarator, declspecs, initialized, raises) use temporary storage. Do this even if we will ignore the value. */ if (current_binding_level == global_binding_level && debug_temp_inits) { - if (TYPE_NEEDS_CONSTRUCTING (type) || TREE_CODE (type) == REFERENCE_TYPE) + if (TYPE_NEEDS_CONSTRUCTING (type) + || TREE_CODE (type) == REFERENCE_TYPE) /* In this case, the initializer must lay down in permanent storage, since it will be saved until `finish_file' is run. */ ; @@ -5463,7 +5553,8 @@ grok_reference_init (decl, type, init, cleanupp) TREE_OPERAND (TREE_OPERAND (tmp, 0), 2) = error_mark_node; } if (IS_AGGR_TYPE (TREE_TYPE (this_ptr_type))) - DECL_INITIAL (decl) = convert_pointer_to (TREE_TYPE (this_ptr_type), tmp); + DECL_INITIAL (decl) = convert_pointer_to (TREE_TYPE (this_ptr_type), + tmp); else DECL_INITIAL (decl) = convert (this_ptr_type, tmp); @@ -5481,7 +5572,8 @@ grok_reference_init (decl, type, init, cleanupp) if (TREE_CODE (actual_init) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (actual_init, 0)) == TARGET_EXPR) actual_init = save_expr (actual_init); - DECL_INITIAL (decl) = convert_pointer_to (TREE_TYPE (this_ptr_type), actual_init); + DECL_INITIAL (decl) = convert_pointer_to (TREE_TYPE (this_ptr_type), + actual_init); DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl)); TREE_TYPE (DECL_INITIAL (decl)) = type; } @@ -5689,7 +5781,8 @@ finish_decl (decl, init, asmspec_tree, need_pop) { if (TYPE_NEEDS_CONSTRUCTING (type)) { - cp_error ("`%D' must be initialized by constructor, not by `{...}'", decl); + cp_error ("`%D' must be initialized by constructor, not by `{...}'", + decl); init = error_mark_node; } else @@ -5780,7 +5873,8 @@ finish_decl (decl, init, asmspec_tree, need_pop) if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (ctype)) cp_error ("structure `%D' with uninitialized const members", decl); if (CLASSTYPE_REF_FIELDS_NEED_INIT (ctype)) - cp_error ("structure `%D' with uninitialized reference members", decl); + cp_error ("structure `%D' with uninitialized reference members", + decl); } if (TREE_CODE (decl) == VAR_DECL @@ -6002,9 +6096,6 @@ finish_decl (decl, init, asmspec_tree, need_pop) } else if (toplev) { - /* Keep GCC from complaining that this variable - is defined but never used. */ - TREE_USED (decl) = 1; /* If this is a static const, change its apparent linkage if it belongs to a #pragma interface. */ if (TREE_STATIC (decl) && !interface_unknown) @@ -6092,7 +6183,8 @@ finish_decl (decl, init, asmspec_tree, need_pop) : & TYPE_ARG_TYPES (type); *argp = NULL_TREE; - fnname = build_decl_overload (original_name, TYPE_ARG_TYPES (type), 0); + fnname = build_decl_overload (original_name, + TYPE_ARG_TYPES (type), 0); *argp = parmtypes; fndecl = build_decl (FUNCTION_DECL, fnname, type); DECL_EXTERNAL (fndecl) = DECL_EXTERNAL (decl); @@ -6169,7 +6261,8 @@ finish_decl (decl, init, asmspec_tree, need_pop) if (init || TYPE_NEEDS_CONSTRUCTING (type)) { - emit_line_note (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); + emit_line_note (DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); expand_aggr_init (decl, init, 0); } @@ -6182,7 +6275,8 @@ finish_decl (decl, init, asmspec_tree, need_pop) if (cleanup) { if (! expand_decl_cleanup (decl, cleanup)) - cp_error ("parser lost in parsing declaration of `%D'", decl); + cp_error ("parser lost in parsing declaration of `%D'", + decl); } } } @@ -6380,7 +6474,8 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises) if (inlinep) cp_error ("`%D' declared as an `inline' %s", object, type); if (quals) - cp_error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration", object, type); + cp_error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration", + object, type); if (friendp) cp_error_at ("invalid friend declaration", object); if (raises) @@ -6399,7 +6494,8 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises) CHECK is 1 if we must find this method in CTYPE, 0 if we should not look, and -1 if we should not call `grokclassfn' at all. */ static tree -grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, check, publicp) +grokfndecl (ctype, type, declarator, virtualp, flags, quals, + raises, check, publicp) tree ctype, type; tree declarator; int virtualp; @@ -6530,7 +6626,8 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, check, publ for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); - if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo)) || flag_all_virtual == 1) + if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo)) + || flag_all_virtual == 1) { tmp = get_first_matching_virtual (base_binfo, decl, flags == DTOR_FLAG); @@ -6547,8 +6644,10 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, check, publ path to its virtual baseclass. */ if (staticp) { - cp_error ("method `%D' may not be declared static", decl); - cp_error_at ("(since `%D' declared virtual in base class.)", tmp); + cp_error ("method `%D' may not be declared static", + decl); + cp_error_at ("(since `%D' declared virtual in base class.)", + tmp); break; } virtualp = 1; @@ -6716,7 +6815,8 @@ build_ptrmemfunc_type (type) u = make_lang_type (UNION_TYPE); fields[0] = build_lang_field_decl (FIELD_DECL, pfn_identifier, type); - fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier, delta_type_node); + fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier, + delta_type_node); finish_builtin_type (u, "__ptrmemfunc_type", fields, 1, ptr_type_node); TYPE_NAME (u) = NULL_TREE; @@ -6725,8 +6825,10 @@ build_ptrmemfunc_type (type) /* Let the front-end know this is a pointer to member function. */ TYPE_PTRMEMFUNC_FLAG(t) = 1; - fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, delta_type_node); - fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier, delta_type_node); + fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, + delta_type_node); + fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier, + delta_type_node); fields[2] = build_lang_field_decl (FIELD_DECL, pfn_or_delta2_identifier, u); finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node); @@ -6839,7 +6941,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) tree ctype = current_class_type; tree ctor_return_type = NULL_TREE; enum overload_flags flags = NO_SPECIAL; - int seen_scope_ref = 0; tree quals = NULL_TREE; RIDBIT_RESET_ALL (specbits); @@ -6957,7 +7058,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) dname = decl; decl = NULL_TREE; - if (IDENTIFIER_TYPENAME_P (dname)) + /* This may just be a variable starting with __op. */ + if (IDENTIFIER_TYPENAME_P (dname) && TREE_TYPE (dname)) { my_friendly_assert (flags == NO_SPECIAL, 154); flags = TYPENAME_FLAG; @@ -6987,11 +7089,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) /* C++ extension */ case SCOPE_REF: -/* - if (seen_scope_ref == 1) - error ("multiple `::' terms in declarator invalid"); -*/ - seen_scope_ref += 1; { /* Perform error checking, and convert class names to types. We may call grokdeclarator multiple times for the same @@ -7239,14 +7336,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) } else { - if (funcdef_flag && warn_return_type - && return_type == return_normal - && ! (RIDBIT_SETP (RID_SIGNED, specbits) - || RIDBIT_SETP (RID_UNSIGNED, specbits) - || RIDBIT_SETP (RID_LONG, specbits) - || RIDBIT_SETP (RID_SHORT, specbits))) - warn_about_return_type = 1; - /* Save warning until we know what is really going on. */ + if (funcdef_flag) + { + if (warn_return_type + && return_type == return_normal + && ! (RIDBIT_SETP (RID_SIGNED, specbits) + || RIDBIT_SETP (RID_UNSIGNED, specbits) + || RIDBIT_SETP (RID_LONG, specbits) + || RIDBIT_SETP (RID_SHORT, specbits))) + /* Save warning until we know what is really going on. */ + warn_about_return_type = 1; + } + else if (class_binding_level && declarator + && TREE_CODE (declarator) == SCOPE_REF) + /* OK -- access declaration */; + else if (declspecs == NULL_TREE && + (innermost_code != CALL_EXPR || pedantic)) + cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type or storage class", + dname); type = integer_type_node; } } @@ -7486,7 +7593,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) } if (volatilep) { - error ("`volatile' specified for signature member function `%s'", name); + error ("`volatile' specified for signature member function `%s'", + name); volatilep = 0; } if (inlinep) @@ -7502,7 +7610,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) } if (virtualp) { - error ("`virtual' specified for signature member function `%s'", name); + error ("`virtual' specified for signature member function `%s'", + name); /* Later, we'll make signature member functions virtual. */ virtualp = 0; } @@ -7816,7 +7925,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) else { if (pedantic) - cp_pedwarn ("ANSI C++ forbids variable-size array `%D'", dname); + cp_pedwarn ("ANSI C++ forbids variable-size array `%D'", + dname); dont_grok_size: itype = build_binary_op (MINUS_EXPR, size, integer_one_node, 1); @@ -8177,11 +8287,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) /* don't fall out into global scope. Hides real bug? --eichin */ ; else if (TREE_COMPLEXITY (declarator) == current_class_depth) { - /* I'm not really sure what pushclass calls this popclass - corresponds to. One is in build_push_scope and that has - been changed to a push_nested_class call, that's why I - try to use pop_nested_class here instead. - -niklas@appli.se */ + /* This pop_nested_class corresponds to the + push_nested_class used to push into class scope for + parsing the argument list of a function decl, in + qualified_id. */ pop_nested_class (1); TREE_COMPLEXITY (declarator) = current_class_depth; } @@ -8631,7 +8740,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) } if (declarator == ansi_opname[(int) NEW_EXPR] - || declarator == ansi_opname[(int) DELETE_EXPR]) + || declarator == ansi_opname[(int) VEC_NEW_EXPR] + || declarator == ansi_opname[(int) DELETE_EXPR] + || declarator == ansi_opname[(int) VEC_DELETE_EXPR]) { if (virtualp) { @@ -9328,7 +9439,8 @@ grok_ctor_properties (ctype, decl) } /* An operator with this name can be either unary or binary. */ -int ambi_op_p (name) +static int +ambi_op_p (name) tree name; { return (name == ansi_opname [(int) INDIRECT_REF] @@ -9340,7 +9452,8 @@ int ambi_op_p (name) } /* An operator with this name can only be unary. */ -int unary_op_p (name) +static int +unary_op_p (name) tree name; { return (name == ansi_opname [(int) TRUTH_NOT_EXPR] @@ -9358,44 +9471,39 @@ grok_op_properties (decl, virtualp, friendp) tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE); tree name = DECL_NAME (decl); - tree t; - if (! friendp) - for (t = current_class_type; t; t = TYPE_NEXT_VARIANT (t)) - { - if (name == ansi_opname[(int) MODIFY_EXPR]) - TYPE_HAS_ASSIGNMENT (t) = 1; - else if (name == ansi_opname[(int) CALL_EXPR]) - TYPE_OVERLOADS_CALL_EXPR (t) = 1; - else if (name == ansi_opname[(int) ARRAY_REF]) - TYPE_OVERLOADS_ARRAY_REF (t) = 1; - else if (name == ansi_opname[(int) COMPONENT_REF] - || name == ansi_opname[(int) MEMBER_REF]) - TYPE_OVERLOADS_ARROW (t) = 1; - else if (name == ansi_opname[(int) NEW_EXPR]) - { - if (TREE_CHAIN (argtypes) == void_list_node) - TREE_GETS_NEW (t) = 1; - else - TREE_GETS_PLACED_NEW (t) = 1; - } - else if (name == ansi_opname[(int) DELETE_EXPR]) - TREE_GETS_DELETE (t) = 1; -#if 0 - else if (name == ansi_opname[(int) VEC_NEW_EXPR]) - TREE_GETS_NEW (t) = 1; - else if (name == ansi_opname[(int) VEC_DELETE_EXPR]) - TREE_GETS_DELETE (t) = 1; -#endif - } + if (current_class_type == NULL_TREE) + friendp = 1; - if (name == ansi_opname[(int) NEW_EXPR]) + if (! friendp) + { + if (name == ansi_opname[(int) MODIFY_EXPR]) + TYPE_HAS_ASSIGNMENT (current_class_type) = 1; + else if (name == ansi_opname[(int) CALL_EXPR]) + TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1; + else if (name == ansi_opname[(int) ARRAY_REF]) + TYPE_OVERLOADS_ARRAY_REF (current_class_type) = 1; + else if (name == ansi_opname[(int) COMPONENT_REF] + || name == ansi_opname[(int) MEMBER_REF]) + TYPE_OVERLOADS_ARROW (current_class_type) = 1; + else if (name == ansi_opname[(int) NEW_EXPR]) + TYPE_GETS_NEW (current_class_type) |= 1; + else if (name == ansi_opname[(int) DELETE_EXPR]) + TYPE_GETS_DELETE (current_class_type) |= 1; + else if (name == ansi_opname[(int) VEC_NEW_EXPR]) + TYPE_GETS_NEW (current_class_type) |= 2; + else if (name == ansi_opname[(int) VEC_DELETE_EXPR]) + TYPE_GETS_DELETE (current_class_type) |= 2; + } + + if (name == ansi_opname[(int) NEW_EXPR] + || name == ansi_opname[(int) VEC_NEW_EXPR]) { -#if 0 /* When the compiler encounters the definition of A::operator new, it doesn't look at the class declaration to find out if it's static. */ - my_friendly_assert (!methodp, 355); -#endif + if (methodp) + revert_static_member_fn (&TREE_TYPE (decl), &decl, + &TYPE_ARG_TYPES (TREE_TYPE (decl))); /* Take care of function decl if we had syntax errors. */ if (argtypes == NULL_TREE) @@ -9404,18 +9512,14 @@ grok_op_properties (decl, virtualp, friendp) hash_tree_chain (integer_type_node, void_list_node)); else - decl = coerce_new_type (TREE_TYPE (decl)); + TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl)); } -#if 0 - else if (name == ansi_opname[(int) VEC_NEW_EXPR]) - { - } -#endif - else if (name == ansi_opname[(int) DELETE_EXPR]) + else if (name == ansi_opname[(int) DELETE_EXPR] + || name == ansi_opname[(int) VEC_DELETE_EXPR]) { -#if 0 - my_friendly_assert (!methodp, 355); -#endif + if (methodp) + revert_static_member_fn (&TREE_TYPE (decl), &decl, + &TYPE_ARG_TYPES (TREE_TYPE (decl))); if (argtypes == NULL_TREE) TREE_TYPE (decl) = @@ -9423,13 +9527,15 @@ grok_op_properties (decl, virtualp, friendp) hash_tree_chain (ptr_type_node, void_list_node)); else - decl = coerce_delete_type (TREE_TYPE (decl)); - } -#if 0 - else if (name == ansi_opname[(int) VEC_DELETE_EXPR]) - { + { + TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl)); + + if (! friendp && name == ansi_opname[(int) VEC_DELETE_EXPR] + && (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl))) + != void_list_node)) + TYPE_VEC_DELETE_TAKES_SIZE (current_class_type) = 1; + } } -#endif else { /* An operator function must either be a non-static member function @@ -9484,8 +9590,9 @@ grok_op_properties (decl, virtualp, friendp) parmtype = TREE_VALUE (TREE_CHAIN (argtypes)); if (TREE_CODE (parmtype) == REFERENCE_TYPE - && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) - == current_class_type) + && (TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) + == current_class_type) + && ! friendp) { TYPE_HAS_ASSIGN_REF (current_class_type) = 1; if (TYPE_READONLY (TREE_TYPE (parmtype))) @@ -9957,9 +10064,8 @@ if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE } TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype); - TREE_GETS_NEW (ref) |= TREE_GETS_NEW (basetype); - TREE_GETS_PLACED_NEW (ref) |= TREE_GETS_PLACED_NEW (basetype); - TREE_GETS_DELETE (ref) |= TREE_GETS_DELETE (basetype); + TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype); + TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype); CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype); i += 1; } @@ -10439,7 +10545,8 @@ start_function (declspecs, declarator, raises, pre_parsed_p) /* If this doesn't return integer_type, complain. */ if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node) { - warning ("return type for `main' changed to integer type"); + if (pedantic || warn_return_type) + warning ("return type for `main' changed to integer type"); TREE_TYPE (decl1) = fntype = default_function_type; } warn_about_return_type = 0; @@ -11040,7 +11147,7 @@ finish_function (lineno, call_poplevel) /* These are two cases where we cannot delegate deletion. */ if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type) - || TREE_GETS_DELETE (current_class_type)) + || TYPE_GETS_REG_DELETE (current_class_type)) exprstmt = build_delete (current_class_type, C_C_D, integer_zero_node, LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); else @@ -11096,7 +11203,7 @@ finish_function (lineno, call_poplevel) virtual_size = c_sizeof (current_class_type); /* At the end, call delete if that's what's requested. */ - if (TREE_GETS_DELETE (current_class_type)) + if (TYPE_GETS_REG_DELETE (current_class_type)) /* This NOP_EXPR means we are in a static call context. */ exprstmt = build_method_call @@ -11216,7 +11323,7 @@ finish_function (lineno, call_poplevel) expand_decl_init (allocated_this); /* How we cleanup `this' if an exception was raised before we are ready to bail out. */ - cleanup = TREE_GETS_DELETE (current_class_type) + cleanup = TYPE_GETS_REG_DELETE (current_class_type) ? build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, allocated_this, virtual_size, NULL_TREE) /* The size of allocated_this is wrong, and hence the second argument to operator delete will be wrong. */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 2177713958c4..aad0c15fe9f3 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1071,6 +1071,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete) return error_mark_node; } +#if 0 /* If the type has no destructor, then we should build a regular delete, instead of a vector delete. Otherwise, we would end up passing a bogus offset into __builtin_delete, which is @@ -1082,15 +1083,15 @@ delete_sanity (exp, size, doing_vec, use_global_delete) doing_vec = 0; use_global_delete = 1; } +#endif if (doing_vec) - return build_vec_delete (t, maxindex, elt_size, NULL_TREE, - integer_one_node, integer_two_node); + return build_vec_delete (t, maxindex, elt_size, integer_one_node, + integer_two_node, use_global_delete); else return build_delete (type, t, integer_three_node, LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE, - use_global_delete - || TYPE_HAS_DESTRUCTOR (TREE_TYPE (type))); + use_global_delete); } /* Sanity check: report error if this function FUNCTION is not @@ -1456,6 +1457,7 @@ grokbitfield (declarator, declspecs, width) return value; } +#if 0 /* Like GROKFIELD, except that the declarator has been buried in DECLSPECS. Find the declarator, and return something that looks like it came from @@ -1634,6 +1636,7 @@ groktypefield (declspecs, parmlist) DECL_IN_AGGR_P (decl) = 1; return decl; } +#endif tree grokoptypename (declspecs, declarator) @@ -2278,7 +2281,7 @@ coerce_delete_type (type) else if (e3 |= e2) { if (arg_types == NULL_TREE) - arg_types = void_list_node; + arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node); else arg_types = tree_cons (NULL_TREE, ptr_type_node, TREE_CHAIN (arg_types)); } @@ -2853,7 +2856,11 @@ reparse_decl_as_expr1 (decl) case BIT_NOT_EXPR: return build_x_unary_op (BIT_NOT_EXPR, reparse_decl_as_expr1 (TREE_OPERAND (decl, 0))); - + case SCOPE_REF: + return build_offset_ref (TREE_OPERAND (decl, 0), TREE_OPERAND (decl, 1)); + case ARRAY_REF: + return grok_array_decl (reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)), + TREE_OPERAND (decl, 1)); default: my_friendly_abort (5); return NULL_TREE; @@ -2901,6 +2908,9 @@ finish_decl_parsing (decl) push_nested_class (TREE_OPERAND (decl, 0), 3); TREE_COMPLEXITY (decl) = current_class_depth; return decl; + case ARRAY_REF: + TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0)); + return decl; default: my_friendly_abort (5); return NULL_TREE; diff --git a/gcc/cp/gxxint.texi b/gcc/cp/gxxint.texi index 1878c86a5142..d27fe70c7917 100644 --- a/gcc/cp/gxxint.texi +++ b/gcc/cp/gxxint.texi @@ -1059,17 +1059,18 @@ It is ambiguous whether @code{class T} should be parsed as the declaration of a template type parameter named @code{T} or an unnamed constant parameter of type @code{class T}. Section 14.6, paragraph 3 of the January '94 working paper states that the first interpretation is -the correct one. This ambiguity results in four reduce/reduce conflicts. +the correct one. This ambiguity results in two reduce/reduce conflicts. -2) Between @code{primary} and @code{typename} for code like @samp{int()} +2) Between @code{primary} and @code{type_id} for code like @samp{int()} in places where both can be accepted, such as the argument to @code{sizeof}. Section 8.1 of the pre-San Diego working paper specifies that these ambiguous constructs will be interpreted as @code{typename}s. -This ambiguity results in six reduce/reduce conflicts. +This ambiguity results in six reduce/reduce conflicts between +@samp{absdcl} and @samp{functional_cast}. -3) Between @code{primary}/@code{functional_cast} and -@code{expr_or_declarator}/@code{complex_direct_notype_declarator}, for -various token strings. This situation occurs in code looking like +3) Between @code{functional_cast} and +@code{complex_direct_notype_declarator}, for various token strings. +This situation occurs in code looking like @example int (*a); @@ -1078,11 +1079,23 @@ int (*a); This code is ambiguous; it could be a declaration of the variable @samp{a} as a pointer to @samp{int}, or it could be a functional cast of @samp{*a} to @samp{int}. Section 6.8 specifies that the former -interpretation is correct. This ambiguity results in 12 reduce/reduce -conflicts. Ack. - -4) Between @code{after_type_declarator} and @code{parm}, for the token -@code{TYPENAME}. This occurs in (as one example) code like +interpretation is correct. This ambiguity results in 7 reduce/reduce +conflicts. Another aspect of this ambiguity is code like 'int (x[2]);', +which is resolved at the '[' and accounts for 6 reduce/reduce conflicts +between @samp{direct_notype_declarator} and +@samp{primary}/@samp{overqualified_id}. Finally, there are 4 r/r +conflicts between @samp{expr_or_declarator} and @samp{primary} over code +like 'int (a);', which could probably be resolved but would also +probably be more trouble than it's worth. In all, this situation +accounts for 17 conflicts. Ack! + +The second case above is responsible for the failure to parse 'LinppFile +ppfile (String (argv[1]), &outs, argc, argv);' (from Rogue Wave +Math.h++) as an object declaration, and must be fixed so that it does +not resolve until later. + +4) Indirectly between @code{after_type_declarator} and @code{parm}, for +type names. This occurs in (as one example) code like @example typedef int foo, bar; @@ -1093,11 +1106,12 @@ class A @{ What is @code{bar} inside the class definition? We currently interpret it as a @code{parm}, as does Cfront, but IBM xlC interprets it as an -@code{after_type_declarator}. I suspect that xlC is correct, in light +@code{after_type_declarator}. I believe that xlC is correct, in light of 7.1p2, which says "The longest sequence of @i{decl-specifiers} that could possibly be a type name is taken as the @i{decl-specifier-seq} of a @i{declaration}." However, it seems clear that this rule must be -violated in the case of constructors, so... +violated in the case of constructors. This ambiguity accounts for 8 +conflicts. Unlike the others, this ambiguity is not recognized by the Working Paper. diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 90ff11cc5299..4d2cbf7332cc 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -52,12 +52,11 @@ static void expand_recursive_init_1 (); static void expand_recursive_init (); static void expand_virtual_init PROTO((tree, tree, tree)); tree expand_vec_init (); -tree build_vec_delete (); static void add_friend (), add_friends (); /* Cache _builtin_new and _builtin_delete exprs. */ -static tree BIN, BID; +static tree BIN, BID, BIVN, BIVD; /* Cache the identifier nodes for the two magic field of a new cookie. */ static tree nc_nelts_field_id; @@ -81,6 +80,10 @@ void init_init_processing () TREE_USED (TREE_OPERAND (BIN, 0)) = 0; BID = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) DELETE_EXPR]))); TREE_USED (TREE_OPERAND (BID, 0)) = 0; + BIVN = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) VEC_NEW_EXPR]))); + TREE_USED (TREE_OPERAND (BIVN, 0)) = 0; + BIVD = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) VEC_DELETE_EXPR]))); + TREE_USED (TREE_OPERAND (BIVD, 0)) = 0; minus_one = build_int_2 (-1, -1); /* Define the structure that holds header information for @@ -1801,12 +1804,10 @@ is_aggr_typedef (name, or_else) if (IDENTIFIER_HAS_TYPE_VALUE (name)) type = IDENTIFIER_TYPE_VALUE (name); - else if (IDENTIFIER_HAS_CLASS_TYPE_VALUE (name)) - type = IDENTIFIER_CLASS_TYPE_VALUE (name); else { if (or_else) - cp_error ("`%T' fails to be an aggregate typedef", name); + cp_error ("`%T' is not an aggregate typedef", name); return 0; } @@ -1814,7 +1815,7 @@ is_aggr_typedef (name, or_else) && TREE_CODE (type) != TEMPLATE_TYPE_PARM) { if (or_else) - cp_error ("type `%T' is of non-aggregate type", type); + cp_error ("`%T' is not an aggregate type", type); return 0; } return 1; @@ -1833,8 +1834,6 @@ get_aggr_from_typedef (name, or_else) if (IDENTIFIER_HAS_TYPE_VALUE (name)) type = IDENTIFIER_TYPE_VALUE (name); - else if (IDENTIFIER_HAS_CLASS_TYPE_VALUE (name)) - type = IDENTIFIER_CLASS_TYPE_VALUE (name); else { if (or_else) @@ -1861,8 +1860,6 @@ get_type_value (name) if (IDENTIFIER_HAS_TYPE_VALUE (name)) return IDENTIFIER_TYPE_VALUE (name); - else if (IDENTIFIER_CLASS_VALUE (name)) - return IDENTIFIER_CLASS_TYPE_VALUE (name); else return NULL_TREE; } @@ -2808,13 +2805,6 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals) TREE_PUBLIC (decl) = 1; add_friend (current_class_type, decl); DECL_FRIEND_P (decl) = 1; - if (IDENTIFIER_POINTER (declarator)[0] == '_') - { - if (! strcmp (IDENTIFIER_POINTER (declarator)+10, "new")) - TREE_GETS_NEW (current_class_type) = 0; - else if (! strcmp (IDENTIFIER_POINTER (declarator)+10, "delete")) - TREE_GETS_DELETE (current_class_type) = 0; - } decl = void_type_node; } /* A global friend. @@ -2980,6 +2970,7 @@ build_new (placement, decl, init, use_global_new) tree type, true_type, size, rval; tree nelts; int has_array = 0; + enum tree_code code = NEW_EXPR; tree pending_sizes = NULL_TREE; @@ -3155,27 +3146,28 @@ build_new (placement, decl, init, use_global_new) /* Get a little extra space to store a couple of things before the new'ed array. */ - if (has_array && TYPE_NEEDS_DESTRUCTOR (true_type)) + if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)) { tree extra = BI_header_size; size = size_binop (PLUS_EXPR, size, extra); } + if (has_array) + code = VEC_NEW_EXPR; + /* Allocate the object. */ - if (TYPE_LANG_SPECIFIC (true_type) - && (TREE_GETS_NEW (true_type) || TREE_GETS_PLACED_NEW (true_type)) - && !use_global_new - && !has_array) - rval = build_opfncall (NEW_EXPR, LOOKUP_NORMAL, + if (! use_global_new && TYPE_LANG_SPECIFIC (true_type) + && (TYPE_GETS_NEW (true_type) & (1 << has_array))) + rval = build_opfncall (code, LOOKUP_NORMAL, TYPE_POINTER_TO (true_type), size, placement); else if (placement) { - rval = build_opfncall (NEW_EXPR, LOOKUP_GLOBAL|LOOKUP_COMPLAIN, + rval = build_opfncall (code, LOOKUP_GLOBAL|LOOKUP_COMPLAIN, ptr_type_node, size, placement); rval = convert (TYPE_POINTER_TO (true_type), rval); } - else if (flag_this_is_variable > 0 + else if (! has_array && flag_this_is_variable > 0 && TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node) { if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST) @@ -3189,7 +3181,8 @@ build_new (placement, decl, init, use_global_new) else { rval = build_builtin_call (build_pointer_type (true_type), - BIN, build_tree_list (NULL_TREE, size)); + has_array ? BIVN : BIN, + build_tree_list (NULL_TREE, size)); #if 0 /* See comment above as to why this is disabled. */ if (alignment) @@ -3202,14 +3195,13 @@ build_new (placement, decl, init, use_global_new) } #endif TREE_CALLS_NEW (rval) = 1; - TREE_SIDE_EFFECTS (rval) = 1; } /* if rval is NULL_TREE I don't have to allocate it, but are we totally sure we have some extra bytes in that case for the BI_header_size cookies? And how does that interact with the code below? (mrs) */ /* Finish up some magic for new'ed arrays */ - if (has_array && TYPE_NEEDS_DESTRUCTOR (true_type) && rval != NULL_TREE) + if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type) && rval != NULL_TREE) { tree extra = BI_header_size; tree cookie, exp1; @@ -3594,20 +3586,21 @@ expand_vec_init (decl, base, maxindex, init, from_array) This does not call any destructors. */ tree -build_x_delete (type, addr, use_global_delete, virtual_size) +build_x_delete (type, addr, which_delete, virtual_size) tree type, addr; - int use_global_delete; + int which_delete; tree virtual_size; { + int use_global_delete = which_delete & 1; + int use_vec_delete = !!(which_delete & 2); tree rval; + enum tree_code code = use_vec_delete ? VEC_DELETE_EXPR : DELETE_EXPR; - if (!use_global_delete - && TYPE_LANG_SPECIFIC (TREE_TYPE (type)) - && TREE_GETS_DELETE (TREE_TYPE (type))) - rval = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr, - virtual_size, NULL_TREE); + if (! use_global_delete && TYPE_LANG_SPECIFIC (TREE_TYPE (type)) + && (TYPE_GETS_DELETE (TREE_TYPE (type)) & (1 << use_vec_delete))) + rval = build_opfncall (code, LOOKUP_NORMAL, addr, virtual_size, NULL_TREE); else - rval = build_builtin_call (void_type_node, BID, + rval = build_builtin_call (void_type_node, use_vec_delete ? BIVD : BID, build_tree_list (NULL_TREE, addr)); return rval; } @@ -3674,7 +3667,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) addr = save_expr (addr); return build_vec_delete (addr, array_type_nelts (type), c_sizeof_nowarn (TREE_TYPE (type)), - NULL_TREE, auto_delete, integer_two_node); + auto_delete, integer_two_node, + use_global_delete); } else { @@ -3707,10 +3701,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) /* Pass the size of the object down to the operator delete() in addition to the ADDR. */ - if (TREE_GETS_DELETE (type) && !use_global_delete) + if (TYPE_GETS_REG_DELETE (type) && !use_global_delete) { - /* This is probably wrong. It should be the size of the virtual - object being deleted. */ tree virtual_size = c_sizeof_nowarn (type); return build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr, virtual_size, NULL_TREE); @@ -3837,7 +3829,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) operator delete, call the parent parent destructor (if any), but let this node do the deleting. Otherwise, it is ok to let the parent destructor do the deleting. */ - if (TREE_GETS_DELETE (type) && !use_global_delete) + if (TYPE_GETS_REG_DELETE (type) && !use_global_delete) { parent_auto_delete = integer_zero_node; if (auto_delete == integer_zero_node) @@ -3970,8 +3962,6 @@ build_vbase_delete (type, decl) MAXINDEX is the number of elements to be deleted. ELT_SIZE is the nominal size of each element in the vector. BASE is the expression that should yield the store to be deleted. - DTOR_DUMMY is a placeholder for a destructor. The library function - __builtin_vec_delete has a pointer to function in this position. This function expands (or synthesizes) these calls itself. AUTO_DELETE_VEC says whether the container (vector) should be deallocated. AUTO_DELETE say whether each item in the container should be deallocated. @@ -3985,10 +3975,11 @@ build_vbase_delete (type, decl) confirm the size, and trap if the numbers differ; not clear that it'd be worth bothering.) */ tree -build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_delete) +build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete, + use_global_delete) tree base, maxindex, elt_size; - tree dtor_dummy; tree auto_delete_vec, auto_delete; + int use_global_delete; { tree ptype = TREE_TYPE (base); tree type; @@ -4081,7 +4072,8 @@ build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_de /* This is the real size */ virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size); body = build_tree_list (NULL_TREE, - build_x_delete (ptr_type_node, base_tbd, 1, + build_x_delete (ptype, base_tbd, + 2 | use_global_delete, virtual_size)); body = build (COND_EXPR, void_type_node, build (BIT_AND_EXPR, integer_type_node, @@ -4124,7 +4116,7 @@ build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_de /* The below is short by BI_header_size */ virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex)); - if (loop == integer_zero_node) + if (! TYPE_VEC_NEW_USES_COOKIE (type)) /* no header */ base_tbd = base; else @@ -4137,7 +4129,8 @@ build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_de /* True size with header. */ virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size); } - deallocate_expr = build_x_delete (ptr_type_node, base_tbd, 1, + deallocate_expr = build_x_delete (ptype, base_tbd, + 2 | use_global_delete, virtual_size); if (auto_delete_vec != integer_one_node) deallocate_expr = build (COND_EXPR, void_type_node, diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 26155a7b707d..478cd106a120 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -542,6 +542,10 @@ init_lex () IDENTIFIER_OPNAME_P (ansi_opname[(int) NEW_EXPR]) = 1; ansi_opname[(int) DELETE_EXPR] = get_identifier ("__dl"); IDENTIFIER_OPNAME_P (ansi_opname[(int) DELETE_EXPR]) = 1; + ansi_opname[(int) VEC_NEW_EXPR] = get_identifier ("__vn"); + IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_NEW_EXPR]) = 1; + ansi_opname[(int) VEC_DELETE_EXPR] = get_identifier ("__vd"); + IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_DELETE_EXPR]) = 1; ansi_opname[(int) TYPE_EXPR] = get_identifier ("__op"); IDENTIFIER_OPNAME_P (ansi_opname[(int) TYPE_EXPR]) = 1; @@ -681,6 +685,8 @@ init_lex () opname_tab[(int) MODIFY_EXPR] = "="; opname_tab[(int) NEW_EXPR] = "new"; opname_tab[(int) DELETE_EXPR] = "delete"; + opname_tab[(int) VEC_NEW_EXPR] = "new []"; + opname_tab[(int) VEC_DELETE_EXPR] = "delete []"; opname_tab[(int) COND_EXPR] = "... ? ... : ..."; opname_tab[(int) CALL_EXPR] = "()"; opname_tab[(int) PLUS_EXPR] = "+"; @@ -841,10 +847,7 @@ yyprint (file, yychar, yylval) case IDENTIFIER_DEFN: case TYPENAME_DEFN: case PTYPENAME_DEFN: - case TYPENAME_COLON: case TYPENAME_ELLIPSIS: - case SCOPED_TYPENAME: - case SCOPED_NAME: case SCSPEC: case PRE_PARSED_CLASS_DECL: t = yylval.ttype; @@ -2324,14 +2327,15 @@ check_newline () register int c; register int token; - lineno++; - - /* Read first nonwhite char on the line. */ + /* Read first nonwhite char on the line. Do this before incrementing the + line number, in case we're at the end of saved text. */ do c = getch (); while (c == ' ' || c == '\t'); + lineno++; + if (c != '#') { /* If not #, return it so caller will use it. */ @@ -3080,12 +3084,13 @@ readescape (ignore_ptr) return c; } -/* Value is 1 if we should try to make the next identifier look like a - typename (when it may be a local variable or a class variable). - Value is 0 if we treat this name in a default fashion. - Value is -1 if we must not see a type name. */ +/* Value is 1 (or 2) if we should try to make the next identifier look like + a typename (when it may be a local variable or a class variable). + Value is 0 if we treat this name in a default fashion. */ int looking_for_typename = 0; +#if 0 +/* NO LONGER USED: Value is -1 if we must not see a type name. */ void dont_see_typename () { @@ -3096,6 +3101,7 @@ dont_see_typename () lastiddecl = 0; } } +#endif #ifdef __GNUC__ extern __inline int identifier_type (); @@ -3119,7 +3125,7 @@ see_typename () looking_for_typename = 0; if (yychar == IDENTIFIER) { - lastiddecl = lookup_name (yylval.ttype, -1); + lastiddecl = lookup_name (yylval.ttype, -2); if (lastiddecl == 0) { if (flag_labels_ok) @@ -3540,7 +3546,6 @@ real_yylex () } if (value == NEW && ! global_bindings_p ()) { - looking_for_typename = 1; value = NEW; goto done; } diff --git a/gcc/cp/lex.h b/gcc/cp/lex.h index 457fa39502dd..5288a0243591 100644 --- a/gcc/cp/lex.h +++ b/gcc/cp/lex.h @@ -114,6 +114,9 @@ extern char *token_buffer; /* Pointer to token buffer. */ /* Back-door communication channel to the lexer. */ extern int looking_for_typename; +/* Tell the lexer where to look for names. */ +extern tree got_scope; + /* Pending language change. Positive is push count, negative is pop count. */ extern int pending_lang_change; diff --git a/gcc/cp/method.c b/gcc/cp/method.c index cdf3d196c761..a39f9a57ae32 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -840,27 +840,22 @@ build_decl_overload (dname, parms, for_method) { char *name = IDENTIFIER_POINTER (dname); - if (dname == ansi_opname[(int) NEW_EXPR] - && parms != NULL_TREE - && TREE_CODE (parms) == TREE_LIST - && TREE_VALUE (parms) == sizetype - && TREE_CHAIN (parms) == void_list_node) - return get_identifier ("__builtin_new"); - else if (dname == ansi_opname[(int) DELETE_EXPR] - && parms != NULL_TREE - && TREE_CODE (parms) == TREE_LIST - && TREE_VALUE (parms) == ptr_type_node - && TREE_CHAIN (parms) == void_list_node) - return get_identifier ("__builtin_delete"); - else if (dname == ansi_opname[(int) DELETE_EXPR] - && parms != NULL_TREE - && TREE_CODE (parms) == TREE_LIST - && TREE_VALUE (parms) == ptr_type_node - && TREE_CHAIN (parms) != NULL_TREE - && TREE_CODE (TREE_CHAIN (parms)) == TREE_LIST - && TREE_VALUE (TREE_CHAIN (parms)) == sizetype - && TREE_CHAIN (TREE_CHAIN (parms)) == void_list_node) - return get_identifier ("__builtin_delete"); + /* member operators new and delete look like methods at this point. */ + if (! for_method && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST) + { + if (TREE_VALUE (parms) == sizetype + && TREE_CHAIN (parms) == void_list_node) + { + if (dname == ansi_opname[(int) NEW_EXPR]) + return get_identifier ("__builtin_new"); + else if (dname == ansi_opname[(int) VEC_NEW_EXPR]) + return get_identifier ("__builtin_vec_new"); + } + else if (dname == ansi_opname[(int) DELETE_EXPR]) + return get_identifier ("__builtin_delete"); + else if (dname == ansi_opname[(int) VEC_DELETE_EXPR]) + return get_identifier ("__builtin_vec_delete"); + } OB_INIT (); if (for_method != 2) @@ -1112,19 +1107,19 @@ build_opfncall (code, flags, xarg1, xarg2, arg3) try_second = 0; break; + case VEC_NEW_EXPR: case NEW_EXPR: { - fnname = ansi_opname[(int) NEW_EXPR]; + tree args = tree_cons (NULL_TREE, xarg2, arg3); + fnname = ansi_opname[(int) code]; if (flags & LOOKUP_GLOBAL) - return build_overload_call (fnname, tree_cons (NULL_TREE, xarg2, arg3), - flags & LOOKUP_COMPLAIN, + return build_overload_call (fnname, args, flags & LOOKUP_COMPLAIN, (struct candidate *)0); rval = build_method_call (build_indirect_ref (build1 (NOP_EXPR, xarg1, error_mark_node), "new"), - fnname, tree_cons (NULL_TREE, xarg2, arg3), - NULL_TREE, flags); + fnname, args, NULL_TREE, flags); if (rval == error_mark_node) /* User might declare fancy operator new, but invoke it like standard one. */ @@ -1136,13 +1131,13 @@ build_opfncall (code, flags, xarg1, xarg2, arg3) } break; + case VEC_DELETE_EXPR: case DELETE_EXPR: { - fnname = ansi_opname[(int) DELETE_EXPR]; + fnname = ansi_opname[(int) code]; if (flags & LOOKUP_GLOBAL) return build_overload_call (fnname, - tree_cons (NULL_TREE, xarg1, - build_tree_list (NULL_TREE, xarg2)), + build_tree_list (NULL_TREE, xarg1), flags & LOOKUP_COMPLAIN, (struct candidate *)0); @@ -1151,7 +1146,7 @@ build_opfncall (code, flags, xarg1, xarg2, arg3) error_mark_node), NULL_PTR), fnname, tree_cons (NULL_TREE, xarg1, - build_tree_list (NULL_TREE, xarg2)), + build_tree_list (NULL_TREE, xarg2)), NULL_TREE, flags); /* This happens when the user mis-declares `operator delete'. Should now be impossible. */ diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 9730a62ad7e5..e199708966a4 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -66,12 +66,16 @@ extern int errno; #endif extern int end_of_file; +extern int current_class_depth; void yyerror (); /* Like YYERROR but do call yyerror. */ #define YYERROR1 { yyerror ("syntax error"); YYERROR; } +#define OP0(NODE) (TREE_OPERAND (NODE, 0)) +#define OP1(NODE) (TREE_OPERAND (NODE, 1)) + /* Contains the statement keyword (if/while/do) to include in an error message if the user supplies an empty conditional expression. */ static char *cond_stmt_keyword; @@ -112,12 +116,6 @@ empty_parms () but they can also serve as typespecs in declarations. */ %token TYPENAME -/* Qualified identifiers that end in a TYPENAME. */ -%token SCOPED_TYPENAME - -/* Qualified identifiers that end in a IDENTIFIER. */ -%token SCOPED_NAME - /* Reserved words that specify storage class. yylval contains an IDENTIFIER_NODE which indicates which one. */ %token SCSPEC @@ -156,11 +154,6 @@ empty_parms () %token TYPEID DYNAMIC_CAST %token SCOPE -/* Special token created by the lexer to separate TYPENAME - from an ABSDCL. This allows us to parse `foo (*pf)()'. */ - -%token START_DECLARATOR - /* Define the operator tokens and their precedences. The value is an integer because, if used, it is the tree code to use in the expression made from the operator. */ @@ -173,7 +166,7 @@ empty_parms () %nonassoc IF %nonassoc ELSE -%left IDENTIFIER TYPENAME PTYPENAME TYPENAME_COLON SCSPEC TYPESPEC TYPE_QUAL ENUM AGGR ELLIPSIS SCOPED_TYPENAME TYPEOF SIGOF START_DECLARATOR OPERATOR +%left IDENTIFIER TYPENAME PTYPENAME SCSPEC TYPESPEC TYPE_QUAL ENUM AGGR ELLIPSIS TYPEOF SIGOF OPERATOR %left '{' ',' ';' @@ -217,30 +210,28 @@ empty_parms () %type compstmt except_stmts ansi_except_stmts implicitly_scoped_stmt %type declarator notype_declarator after_type_declarator -%type notype_declarator1 after_type_declarator1 %type direct_notype_declarator direct_after_type_declarator %type structsp opt.component_decl_list component_decl_list %type component_decl components component_declarator %type notype_components notype_component_declarator %type after_type_component_declarator after_type_component_declarator0 -%type notype_component_declarator0 +%type notype_component_declarator0 component_decl_1 %type enumlist enumerator -%type type_id absdcl absdcl1 type_quals +%type type_id absdcl type_quals %type direct_abstract_declarator conversion_declarator %type new_type_id new_declarator direct_new_declarator %type xexpr parmlist parms parm bad_parm %type identifiers_or_typenames %type fcast_or_absdcl regcast_or_absdcl sub_cast_expr -%type expr_or_declarator complex_notype_declarator1 -%type notype_unqualified_id +%type expr_or_declarator complex_notype_declarator +%type notype_unqualified_id unqualified_id qualified_id +%type overqualified_id notype_qualified_id %type complex_direct_notype_declarator functional_cast %type named_parm complex_parmlist typed_declspecs1 parms_comma /* C++ extensions */ -%type typename_scope -%token TYPENAME_COLON TYPENAME_ELLIPSIS -%token PTYPENAME SCOPED_TYPENAME SCOPED_NAME +%token TYPENAME_ELLIPSIS PTYPENAME %token PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL %token PRE_PARSED_CLASS_DECL %type fn.def1 /* Not really! */ @@ -251,21 +242,26 @@ empty_parms () %type base_class_access_list %type base_class maybe_base_class_list base_class.1 %type maybe_raises raise_identifier raise_identifiers ansi_raise_identifier ansi_raise_identifiers -%type component_declarator0 id_scope scoped_typename scoped_base_class -%type forhead.1 identifier_or_opname operator_name -%type new delete object aggr +%type component_declarator0 +%type forhead.1 operator_name +%type new object aggr +%type delete /* %type primary_no_id */ %type nonmomentary_expr %type forhead.2 initdcl0 notype_initdcl0 member_init_list %type .scope try ansi_try %type template_header template_parm_list template_parm %type template_type template_arg_list template_arg -%type template_instantiation template_type_name tmpl.1 tmpl.2 +%type template_instantiation template_type_name tmpl.2 %type template_instantiate_once template_instantiate_some %type fn_tmpl_end /* %type try_for_typename */ %type condition partially_scoped_stmt xcond paren_cond_or_null %type .kindof_pushlevel +%type type_name nested_name_specifier nested_type ptr_to_mem +%type qualified_type_name complete_type_name notype_identifier +%type complex_type_name nested_name_specifier_1 +%type nomods_initdecls nomods_initdcl0 /* in order to recognize aggr tags as defining and thus shadowing. */ %token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN @@ -405,15 +401,6 @@ template_parm: warning ("restricted template type parameters not yet implemented"); $$ = build_tree_list ($2, $4); } - | aggr TYPENAME_COLON base_class.1 - { - if ($1 == signature_type_node) - sorry ("signature as template type parameter"); - else if ($1 != class_type_node) - error ("template type parameter must use keyword `class'"); - warning ("restricted template type parameters not yet implemented"); - $$ = build_tree_list ($2, $3); - } | parm ; @@ -528,11 +515,8 @@ fn_tmpl_end: '{' { $$ = '{'; } ; datadef: - notype_initdecls ';' - { if (pedantic) - pedwarn ("ANSI C++ forbids data definition with no type or storage class"); - else if (! flag_traditional && ! have_extern_spec) - warning ("data definition has no type or storage class"); } + nomods_initdecls ';' + {} | declmods notype_initdecls ';' {} /* Normal case to make fast: "const i;". */ @@ -649,26 +633,6 @@ fn.def1: YYERROR1; reinit_parse_for_function (); $$ = NULL_TREE; } - | TYPENAME '(' parmlist ')' type_quals maybe_raises - { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, $3, $5), $6, 0)) - YYERROR1; - reinit_parse_for_function (); - $$ = NULL_TREE; } - | scoped_typename '(' parmlist ')' type_quals maybe_raises - { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, $3, $5), $6, 0)) - YYERROR1; - reinit_parse_for_function (); - $$ = NULL_TREE; } - | TYPENAME LEFT_RIGHT type_quals maybe_raises - { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, empty_parms (), $3), $4, 0)) - YYERROR1; - reinit_parse_for_function (); - $$ = NULL_TREE; } - | scoped_typename LEFT_RIGHT type_quals maybe_raises - { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, empty_parms (), $3), $4, 0)) - YYERROR1; - reinit_parse_for_function (); - $$ = NULL_TREE; } | PRE_PARSED_FUNCTION_DECL { start_function (NULL_TREE, TREE_VALUE ($$), NULL_TREE, 1); reinit_parse_for_function (); } @@ -679,8 +643,9 @@ fn.def1: fn.def2: typed_declspecs '(' parmlist ')' type_quals maybe_raises { - tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), $3, $5); - $$ = start_method (TREE_CHAIN ($$), decl, $6); + $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1), $3, $5); + $$ = start_method (TREE_CHAIN ($1), $$, $6); + rest_of_mdef: if (! $$) YYERROR1; if (yychar == YYEMPTY) @@ -688,52 +653,17 @@ fn.def2: reinit_parse_for_method (yychar, $$); } | typed_declspecs LEFT_RIGHT type_quals maybe_raises { - tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), empty_parms (), $3); - $$ = start_method (TREE_CHAIN ($$), decl, $4); - if (! $$) - YYERROR1; - if (yychar == YYEMPTY) - yychar = YYLEX; - reinit_parse_for_method (yychar, $$); } + $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1), + empty_parms (), $3); + $$ = start_method (TREE_CHAIN ($1), $$, $4); + goto rest_of_mdef; + } | typed_declspecs declarator maybe_raises - { $$ = start_method ($$, $2, $3); - if (! $$) - YYERROR1; - if (yychar == YYEMPTY) - yychar = YYLEX; - reinit_parse_for_method (yychar, $$); } - | declmods '(' parmlist ')' type_quals maybe_raises - { - tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), $3, $5); - $$ = start_method (TREE_CHAIN ($$), decl, $6); - if (! $$) - YYERROR1; - if (yychar == YYEMPTY) - yychar = YYLEX; - reinit_parse_for_method (yychar, $$); } - | declmods LEFT_RIGHT type_quals maybe_raises - { - tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), empty_parms (), $3); - $$ = start_method (TREE_CHAIN ($$), decl, $4); - if (! $$) - YYERROR1; - if (yychar == YYEMPTY) - yychar = YYLEX; - reinit_parse_for_method (yychar, $$); } + { $$ = start_method ($$, $2, $3); goto rest_of_mdef; } | declmods notype_declarator maybe_raises - { $$ = start_method ($$, $2, $3); - if (! $$) - YYERROR1; - if (yychar == YYEMPTY) - yychar = YYLEX; - reinit_parse_for_method (yychar, $$); } + { $$ = start_method ($$, $2, $3); goto rest_of_mdef; } | notype_declarator maybe_raises - { $$ = start_method (NULL_TREE, $$, $2); - if (! $$) - YYERROR1; - if (yychar == YYEMPTY) - yychar = YYLEX; - reinit_parse_for_method (yychar, $$); } + { $$ = start_method (NULL_TREE, $$, $2); goto rest_of_mdef; } ; return_id: RETURN IDENTIFIER @@ -811,27 +741,22 @@ member_init: '(' nonnull_exprlist ')' pedwarn ("anachronistic old style base class initializer"); expand_member_init (C_C_D, NULL_TREE, void_type_node); } - | identifier '(' nonnull_exprlist ')' - { - expand_member_init (C_C_D, $$, $3); - } - | identifier LEFT_RIGHT - { expand_member_init (C_C_D, $$, void_type_node); } - | template_type_name '(' nonnull_exprlist ')' + | notype_identifier '(' nonnull_exprlist ')' { expand_member_init (C_C_D, $$, $3); } - | template_type_name LEFT_RIGHT + | notype_identifier LEFT_RIGHT { expand_member_init (C_C_D, $$, void_type_node); } - | scoped_typename '(' nonnull_exprlist ')' + | complete_type_name '(' nonnull_exprlist ')' { expand_member_init (C_C_D, $$, $3); } - | scoped_typename LEFT_RIGHT + | complete_type_name LEFT_RIGHT { expand_member_init (C_C_D, $$, void_type_node); } - | id_scope identifier '(' nonnull_exprlist ')' + /* GNU extension */ + | notype_qualified_id '(' nonnull_exprlist ')' { - do_member_init ($$, $2, $4); + do_member_init (OP0 ($1), OP1 ($1), $3); } - | id_scope identifier LEFT_RIGHT + | notype_qualified_id LEFT_RIGHT { - do_member_init ($$, $2, void_type_node); + do_member_init (OP0 ($1), OP1 ($1), void_type_node); } ; @@ -841,23 +766,17 @@ identifier: | PTYPENAME ; +notype_identifier: + IDENTIFIER + | PTYPENAME %prec EMPTY + ; + identifier_defn: IDENTIFIER_DEFN | TYPENAME_DEFN | PTYPENAME_DEFN ; -identifier_or_opname: - IDENTIFIER - | TYPENAME - | PTYPENAME -/* | '~' TYPENAME - { $$ = build_parse_node (BIT_NOT_EXPR, $2); }*/ - /* get rid of the next line, replace it with the above */ - | '~' identifier { $$ = build_parse_node (BIT_NOT_EXPR,$2);} - | operator_name - ; - explicit_instantiation: TEMPLATE aggr template_type | TEMPLATE typed_declspecs declarator @@ -865,32 +784,8 @@ explicit_instantiation: ; template_type: - template_type_name tmpl.1 template_instantiation - { - extern tree template_type_seen_before_scope; - - if ($3) - $$ = $3; - else if ($$ != error_mark_node) - $$ = IDENTIFIER_TYPE_VALUE ($$); - /* This is a kludge: In order to detect nested types inside - * template classes, we have to tell the lexer that it should - * try to replace a following SCOPE token with the correct - * SCOPED_TYPENAME for the nested type. This SCOPED_TYPENAME - * token will be handled in the rule "scoped_typename". - * - niklas@appli.se */ - if (yychar == SCOPE) - { - /* We set template_type_seen_before_scope to be - an error_mark_node so we can avoid meaningless - and unhelpful syntax errors later. */ - if ($$ != error_mark_node) - template_type_seen_before_scope = TYPE_IDENTIFIER ($$); - else - template_type_seen_before_scope = error_mark_node; - yychar = YYLEX; - } - } + template_type_name tmpl.2 template_instantiation + { if ($3) $$ = $3; } ; template_type_name: @@ -900,16 +795,7 @@ template_type_name: { $$ = lookup_template_class ($$, $3, NULL_TREE); } ; -tmpl.1: - /* Expansion of template may be required, unless we're followed by - a class definition. */ - '{' { yyungetc ('{', 1); $$ = 0; } - | ':' { yyungetc (':', 1); $$ = 0; } - | /* empty */ %prec EMPTY - { $$ = instantiate_class_template ($0, 1); } - ; - -tmpl.2: +tmpl.2: %prec EMPTY /* Always do expansion if it hasn't been done already. */ { $$ = instantiate_class_template ($0, 1); } ; @@ -961,7 +847,7 @@ template_instantiate_once: } left_curly opt.component_decl_list '}' { - $$ = finish_struct ($3, $5, 0); + tree t = finish_struct ($3, $5, 0); pop_obstacks (); end_template_instantiation ($1); @@ -971,7 +857,7 @@ template_instantiate_once: pop_tinst_level(); - CLASSTYPE_GOT_SEMICOLON ($$) = 1; + CLASSTYPE_GOT_SEMICOLON (t) = 1; } ; @@ -1229,20 +1115,15 @@ unary_expr: | .scope new '(' nonnull_exprlist ')' '(' type_id ')' { $$ = build_new ($4, groktypename ($7), NULL_TREE, $$ != NULL_TREE); } - /* Unswallow a ':' which is probably meant for ?: expression. */ - | .scope new TYPENAME_COLON - { yyungetc (':', 1); $$ = build_new ($2, $3, NULL_TREE, $$ != NULL_TREE); } - | .scope new '(' nonnull_exprlist ')' TYPENAME_COLON - { yyungetc (':', 1); $$ = build_new ($4, $6, NULL_TREE, $$ != NULL_TREE); } | delete cast_expr %prec UNARY - { $$ = delete_sanity ($2, NULL_TREE, 0, $$ != NULL_TREE); } + { $$ = delete_sanity ($2, NULL_TREE, 0, $1); } | delete '[' ']' cast_expr %prec UNARY - { $$ = delete_sanity ($4, NULL_TREE, 1, $$ != NULL_TREE); + { $$ = delete_sanity ($4, NULL_TREE, 1, $1); if (yychar == YYEMPTY) yychar = YYLEX; } | delete '[' expr ']' cast_expr %prec UNARY - { $$ = delete_sanity ($5, $3, 2, $$ != NULL_TREE); + { $$ = delete_sanity ($5, $3, 2, $1); if (yychar == YYEMPTY) yychar = YYLEX; } ; @@ -1368,33 +1249,33 @@ expr_no_commas: ; notype_unqualified_id: - '~' see_typename TYPENAME - { - destructor_name: - $$ = build_parse_node (BIT_NOT_EXPR, $3); - } - | '~' see_typename IDENTIFIER - { goto destructor_name; } - | '~' see_typename PTYPENAME - { goto destructor_name; } + '~' see_typename identifier + { $$ = build_parse_node (BIT_NOT_EXPR, $3); } | operator_name | IDENTIFIER | PTYPENAME %prec EMPTY ; +unqualified_id: + notype_unqualified_id + | TYPENAME + ; + expr_or_declarator: - '*' expr_or_declarator %prec UNARY + notype_unqualified_id + | notype_qualified_id + | '*' expr_or_declarator %prec UNARY { $$ = build_parse_node (INDIRECT_REF, $2); } | '&' expr_or_declarator %prec UNARY { $$ = build_parse_node (ADDR_EXPR, $2); } - | notype_unqualified_id - { see_typename (); } ; direct_notype_declarator: complex_direct_notype_declarator | notype_unqualified_id - { see_typename (); } + | notype_qualified_id + { push_nested_class (TREE_TYPE (OP0 ($$)), 3); + TREE_COMPLEXITY ($$) = current_class_depth; } ; primary: @@ -1474,10 +1355,6 @@ primary: } | primary '[' expr ']' { $$ = grok_array_decl ($$, $3); } - | object identifier_or_opname %prec UNARY - { $$ = build_component_ref ($$, $2, NULL_TREE, 1); } - | object id_scope identifier_or_opname %prec UNARY - { $$ = build_object_ref ($$, $2, $3); } | primary PLUSPLUS { /* If we get an OFFSET_REF, turn it into what it really means (e.g., a COMPONENT_REF). This way if we've got, @@ -1569,7 +1446,7 @@ primary: | TYPEID '(' type_id ')' { tree type = groktypename ($3); $$ = get_typeid (type); } - | SCOPE IDENTIFIER + | global_scope IDENTIFIER { do_scoped_id: $$ = IDENTIFIER_GLOBAL_VALUE ($2); @@ -1608,19 +1485,24 @@ primary: } } - | SCOPE operator_name + | global_scope operator_name { + got_scope = NULL_TREE; if (TREE_CODE ($2) == IDENTIFIER_NODE) goto do_scoped_id; $$ = $2; } - | id_scope identifier_or_opname %prec HYPERUNARY - { $$ = build_offset_ref ($$, $2); } - | id_scope identifier_or_opname '(' nonnull_exprlist ')' - { $$ = build_member_call ($$, $2, $4); } - | id_scope identifier_or_opname LEFT_RIGHT - { $$ = build_member_call ($$, $2, NULL_TREE); } - | object identifier_or_opname '(' nonnull_exprlist ')' + | overqualified_id %prec HYPERUNARY + { $$ = build_offset_ref (OP0 ($$), OP1 ($$)); } + | overqualified_id '(' nonnull_exprlist ')' + { $$ = build_member_call (OP0 ($$), OP1 ($$), $3); } + | overqualified_id LEFT_RIGHT + { $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); } + | object unqualified_id %prec UNARY + { $$ = build_component_ref ($$, $2, NULL_TREE, 1); } + | object qualified_id %prec UNARY + { $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); } + | object unqualified_id '(' nonnull_exprlist ')' { #if 0 /* This is a future direction of this code, but because @@ -1635,7 +1517,7 @@ primary: (LOOKUP_NORMAL|LOOKUP_AGGR)); #endif } - | object identifier_or_opname LEFT_RIGHT + | object unqualified_id LEFT_RIGHT { #if 0 /* This is a future direction of this code, but because @@ -1650,27 +1532,27 @@ primary: (LOOKUP_NORMAL|LOOKUP_AGGR)); #endif } - | object id_scope identifier_or_opname '(' nonnull_exprlist ')' + | object qualified_id '(' nonnull_exprlist ')' { - if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE ($2))) + if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2)))) { warning ("signature name in scope resolution ignored"); - $$ = build_method_call ($$, $3, $5, NULL_TREE, + $$ = build_method_call ($$, OP1 ($2), $4, NULL_TREE, (LOOKUP_NORMAL|LOOKUP_AGGR)); } else - $$ = build_scoped_method_call ($$, $2, $3, $5); + $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4); } - | object id_scope identifier_or_opname LEFT_RIGHT + | object qualified_id LEFT_RIGHT { - if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE ($2))) + if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2)))) { warning ("signature name in scope resolution ignored"); - $$ = build_method_call ($$, $3, NULL_TREE, NULL_TREE, + $$ = build_method_call ($$, OP1 ($2), NULL_TREE, NULL_TREE, (LOOKUP_NORMAL|LOOKUP_AGGR)); } else - $$ = build_scoped_method_call ($$, $2, $3, NULL_TREE); + $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), NULL_TREE); } /* p->int::~int() is valid -- 12.4 */ | object '~' TYPESPEC LEFT_RIGHT @@ -1741,17 +1623,14 @@ new: NEW .scope: /* empty */ { $$ = 0; } - | SCOPE - { $$ = 1; } + | global_scope + { got_scope = NULL_TREE; $$ = 1; } ; delete: DELETE - { $$ = NULL_TREE; } - | SCOPE delete - { if ($2) - error ("extra `::' before `delete' ignored"); - $$ = error_mark_node; - } + { $$ = 0; } + | global_scope delete + { got_scope = NULL_TREE; $$ = 1; } ; /* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */ @@ -1782,18 +1661,16 @@ object: primary '.' ; decl: - typed_declspecs initdecls ';' - { - resume_momentary ($2); - note_list_got_semicolon ($1); - } - | typespec initdecls ';' - { - resume_momentary ($2); + /* Normal case: make this fast. */ + typespec declarator ';' + { tree d = get_decl_list ($1); + int yes = suspend_momentary (); + d = start_decl ($2, d, 0, NULL_TREE); + finish_decl (d, NULL_TREE, NULL_TREE, 0); + resume_momentary (yes); if (IS_AGGR_TYPE_CODE (TREE_CODE ($1))) note_got_semicolon ($1); } - /* Normal case: make this fast. */ | typed_declspecs declarator ';' { tree d = $1; int yes = suspend_momentary (); @@ -1802,29 +1679,23 @@ decl: resume_momentary (yes); note_list_got_semicolon ($1); } - | typespec declarator ';' - { tree d = get_decl_list ($1); - int yes = suspend_momentary (); - d = start_decl ($2, d, 0, NULL_TREE); - finish_decl (d, NULL_TREE, NULL_TREE, 0); - resume_momentary (yes); + | typespec initdecls ';' + { + resume_momentary ($2); if (IS_AGGR_TYPE_CODE (TREE_CODE ($1))) note_got_semicolon ($1); } - | declmods notype_initdecls ';' - { resume_momentary ((int) $2); } - /* Normal case: make this fast. */ - | declmods notype_declarator ';' - { tree d; - int yes = suspend_momentary (); - d = start_decl ($2, $$, 0, NULL_TREE); - finish_decl (d, NULL_TREE, NULL_TREE, 0); - resume_momentary (yes); + | typed_declspecs initdecls ';' + { + resume_momentary ($2); + note_list_got_semicolon ($1); } + | declmods notype_initdecls ';' + { resume_momentary ($2); } | typed_declspecs ';' { - shadow_tag ($$); - note_list_got_semicolon ($$); + shadow_tag ($1); + note_list_got_semicolon ($1); } | declmods ';' { warning ("empty declaration"); } @@ -1950,22 +1821,7 @@ reserved_typespecquals: typespec: structsp | TYPESPEC %prec EMPTY - | TYPENAME %prec EMPTY - | scoped_typename %prec EMPTY - | SCOPE TYPENAME %prec EMPTY - { $$ = IDENTIFIER_GLOBAL_VALUE ($2); - if (!$$) - { - error ("undeclared variable `%s' (first use here)", - IDENTIFIER_POINTER ($2)); - $$ = error_mark_node; - IDENTIFIER_GLOBAL_VALUE ($2) = error_mark_node; - } - else - { - $$ = TREE_TYPE($$); - } - } + | complete_type_name | TYPEOF '(' expr ')' { $$ = TREE_TYPE ($3); if (pedantic) @@ -2002,7 +1858,6 @@ typespec: structsp $$ = error_mark_node; } } - | template_type %prec EMPTY ; /* A typespec that is a reserved word, or a type qualifier. */ @@ -2022,6 +1877,11 @@ notype_initdecls: | notype_initdecls ',' initdcl ; +nomods_initdecls: + nomods_initdcl0 + | nomods_initdecls ',' initdcl + ; + maybeasm: /* empty */ { $$ = NULL_TREE; } @@ -2098,6 +1958,25 @@ notype_initdcl0: finish_decl (d, NULL_TREE, $3, 0); } ; +nomods_initdcl0: + notype_declarator maybe_raises maybeasm maybe_attribute '=' + { current_declspecs = NULL_TREE; + $5 = suspend_momentary (); + $$ = start_decl ($1, current_declspecs, 1, $2); + cplus_decl_attributes ($$, $4); } + init +/* Note how the declaration of the variable is in effect while its init is parsed! */ + { finish_decl ($6, $7, $3, 0); + $$ = $5; } + | notype_declarator maybe_raises maybeasm maybe_attribute + { tree d; + current_declspecs = NULL_TREE; + $$ = suspend_momentary (); + d = start_decl ($1, current_declspecs, 0, $2); + cplus_decl_attributes (d, $4); + finish_decl (d, NULL_TREE, $3, 0); } + ; + /* the * rules are dummies to accept the Apollo extended syntax so that the header files compile. */ maybe_attribute: @@ -2223,6 +2102,8 @@ structsp: check_for_missing_semicolon ($$); } | ENUM identifier { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 0); } + | ENUM complex_type_name + { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 0); } /* C++ extensions, merged with C to avoid shift/reduce conflicts */ | class_head left_curly opt.component_decl_list '}' @@ -2319,11 +2200,11 @@ aggr: AGGR named_class_head_sans_basetype: aggr identifier - { aggr1: current_aggr = $$; $$ = $2; } - | aggr template_type_name %prec EMPTY { current_aggr = $$; $$ = $2; } - | aggr TYPENAME_COLON - { yyungetc (':', 1); goto aggr1; } + | aggr complex_type_name + { current_aggr = $$; $$ = $2; } + | aggr template_type %prec EMPTY + { current_aggr = $$; $$ = $2; } | aggr template_type_name '{' { yyungetc ('{', 1); aggr2: @@ -2415,10 +2296,6 @@ base_class: else $$ = build_tree_list ((tree)access_default, $$); } - | scoped_base_class - { - goto do_base_class1; - } | base_class_access_list base_class.1 { tree type; @@ -2448,36 +2325,10 @@ base_class: else $$ = build_tree_list ((tree) $$, $2); } - | base_class_access_list scoped_base_class - { - goto do_base_class2; - } ; -scoped_base_class: - base_class.1 SCOPED_TYPENAME - { - /* Kludge!!! See rule "template_type" and the code - * dealing with "template_type_seen_before_scope" in - * yylex(). */ - $$ = $2; - } - ; base_class.1: - template_type_name tmpl.2 template_instantiation - { - extern tree template_type_seen_before_scope; - tree id = $3 ? TYPE_IDENTIFIER ($3) : $1; - - /* Check the rule template_type to get this... */ - if (yychar == YYEMPTY) - yychar = YYLEX; - if (yychar == SCOPE) { - template_type_seen_before_scope = id; - yychar = YYLEX; - } - } - | identifier + complete_type_name | SIGOF '(' expr ')' { if (current_aggr == signature_type_node) @@ -2585,9 +2436,11 @@ left_curly: '{' } pushclass ($0, 0); TYPE_BEING_DEFINED ($0) = 1; +#if 0 t = TYPE_IDENTIFIER ($0); if (t && IDENTIFIER_TEMPLATE (t)) overload_template_name (t, 1); +#endif } ; @@ -2642,81 +2495,58 @@ component_decl_list: ; component_decl: - /* Do not add a "typed_declspecs declarator ';'" rule here for + component_decl_1 ';' + | component_decl_1 '}' + { error ("missing ';' before right brace"); + yyungetc ('}', 0); } + /* C++: handle constructors, destructors and inline functions */ + /* note that INLINE is like a TYPESPEC */ + | fn.def2 ':' /* base_init compstmt */ + { $$ = finish_method ($$); } + | fn.def2 '{' /* nodecls compstmt */ + { $$ = finish_method ($$); } + ; + +component_decl_1: + /* Do not add a "typed_declspecs declarator" rule here for speed; we need to call grok_x_components for enums, so the speedup would be insignificant. */ - typed_declspecs components ';' + typed_declspecs components { $$ = grok_x_components ($$, $2); end_exception_decls (); } - /* These rules introduce a reduce/reduce conflict; in - typedef int foo, bar; - class A { - foo (bar); - }; - should "A::foo" be declared as a function or data member? - In other words, is "bar" an after_type_declarator or a parmlist? */ - | typed_declspecs '(' parmlist ')' ';' - { $$ = groktypefield ($$, $3); } - | typed_declspecs '(' parmlist ')' '}' - { error ("missing ';' before right brace"); - yyungetc ('}', 0); - $$ = groktypefield ($$, $3); } - | typed_declspecs LEFT_RIGHT ';' - { $$ = groktypefield ($$, empty_parms ()); } - | typed_declspecs LEFT_RIGHT '}' - { error ("missing ';' before right brace"); - yyungetc ('}', 0); - $$ = groktypefield ($$, empty_parms ()); } - | declmods notype_components ';' + | declmods notype_components { $$ = grok_x_components ($$, $2); end_exception_decls (); } - /* Normal case: make this fast. */ - | declmods notype_declarator ';' - { $$ = grokfield ($2, $$, - NULL_TREE, NULL_TREE, NULL_TREE); } - | declmods notype_components '}' - { error ("missing ';' before right brace"); - yyungetc ('}', 0); - $$ = grok_x_components ($$, $2); - end_exception_decls (); - } - | declmods '(' parmlist ')' ';' - { $$ = groktypefield ($$, $3); } - | declmods '(' parmlist ')' '}' - { error ("missing ';' before right brace"); - yyungetc ('}', 0); - $$ = groktypefield ($$, $3); } - | declmods LEFT_RIGHT ';' - { $$ = groktypefield ($$, empty_parms ()); } - | declmods LEFT_RIGHT '}' - { error ("missing ';' before right brace"); - yyungetc ('}', 0); - $$ = groktypefield ($$, empty_parms ()); } - | ':' expr_no_commas ';' + | notype_declarator maybe_raises maybeasm maybe_attribute + { $$ = grokfield ($$, NULL_TREE, $2, NULL_TREE, $3); + cplus_decl_attributes ($$, $4); } + | ':' expr_no_commas { $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); } - | ':' expr_no_commas '}' - { error ("missing ';' before right brace"); - yyungetc ('}', 0); - $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); } | error { $$ = NULL_TREE; } - /* C++: handle constructors, destructors and inline functions */ - /* note that INLINE is like a TYPESPEC */ - | fn.def2 ':' /* base_init compstmt */ - { $$ = finish_method ($$); } - | fn.def2 '{' /* nodecls compstmt */ - { $$ = finish_method ($$); } - | notype_declarator maybe_raises ';' - { $$ = grokfield ($$, NULL_TREE, $2, NULL_TREE, NULL_TREE); } - | notype_declarator maybe_raises '}' - { error ("missing ';' before right brace"); - yyungetc ('}', 0); - $$ = grokfield ($$, NULL_TREE, $2, NULL_TREE, NULL_TREE); } + /* These rules introduce a reduce/reduce conflict; in + typedef int foo, bar; + class A { + foo (bar); + }; + should "A::foo" be declared as a function or "A::bar" as a data + member? In other words, is "bar" an after_type_declarator or a + parmlist? */ + | typed_declspecs '(' parmlist ')' type_quals + { $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1), + $3, $5); + $$ = grokfield ($$, TREE_CHAIN ($1), NULL_TREE, NULL_TREE, + NULL_TREE); } + | typed_declspecs LEFT_RIGHT type_quals + { $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1), + empty_parms (), $3); + $$ = grokfield ($$, TREE_CHAIN ($1), NULL_TREE, NULL_TREE, + NULL_TREE); } ; /* The case of exactly one component is handled directly by component_decl. */ @@ -2850,13 +2680,6 @@ new_type_id: { $$ = build_decl_list ($$, NULL_TREE); } ; -/* ANSI abstract-declarator (8.1) */ -absdcl: - absdcl1 %prec EMPTY - | START_DECLARATOR absdcl1 %prec EMPTY - { $$ = $2; } - ; - type_quals: /* empty */ %prec EMPTY { $$ = NULL_TREE; } @@ -2883,32 +2706,31 @@ nonmomentary_expr: /* A declarator that is allowed only after an explicit typespec. */ /* may all be followed by prec '.' */ after_type_declarator: - after_type_declarator1 - | START_DECLARATOR after_type_declarator1 - { $$ = $2; } - ; - -after_type_declarator1: - '*' nonempty_type_quals after_type_declarator1 %prec UNARY + '*' nonempty_type_quals after_type_declarator %prec UNARY { $$ = make_pointer_declarator ($2, $3); } - | '&' nonempty_type_quals after_type_declarator1 %prec UNARY + | '&' nonempty_type_quals after_type_declarator %prec UNARY { $$ = make_reference_declarator ($2, $3); } - | '*' after_type_declarator1 %prec UNARY + | '*' after_type_declarator %prec UNARY { $$ = make_pointer_declarator (NULL_TREE, $2); } - | '&' after_type_declarator1 %prec UNARY + | '&' after_type_declarator %prec UNARY { $$ = make_reference_declarator (NULL_TREE, $2); } - | id_scope '*' type_quals after_type_declarator1 - { tree arg = make_pointer_declarator ($3, $4); - if (TREE_CODE ($$) != SCOPE_REF) - $$ = build_push_scope ($$, arg); - else if (TREE_OPERAND ($$, 1) == NULL_TREE) - TREE_OPERAND ($$, 1) = arg; - else - $$ = build_parse_node (SCOPE_REF, $$, arg); + | ptr_to_mem type_quals after_type_declarator + { tree arg = make_pointer_declarator ($2, $3); + $$ = build_parse_node (SCOPE_REF, $1, arg); } | direct_after_type_declarator ; +qualified_type_name: + type_name %prec EMPTY + | nested_type + ; + +nested_type: + nested_name_specifier type_name %prec EMPTY + { $$ = $2; } + ; + direct_after_type_declarator: direct_after_type_declarator '(' nonnull_exprlist ')' type_quals %prec '.' { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); } @@ -2922,58 +2744,46 @@ direct_after_type_declarator: { $$ = build_parse_node (ARRAY_REF, $$, $3); } | direct_after_type_declarator '[' ']' { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); } - | '(' after_type_declarator1 ')' + | '(' after_type_declarator ')' { $$ = $2; } - | TYPENAME %prec EMPTY + | nested_name_specifier type_name %prec EMPTY + { push_nested_class (TREE_TYPE ($$), 3); + $$ = build_parse_node (SCOPE_REF, $$, $2); + TREE_COMPLEXITY ($$) = current_class_depth; } + | type_name %prec EMPTY ; /* A declarator allowed whether or not there has been an explicit typespec. These cannot redeclare a typedef-name. */ notype_declarator: - notype_declarator1 - | START_DECLARATOR notype_declarator1 - { $$ = $2; } - ; - -notype_declarator1: - '*' nonempty_type_quals notype_declarator1 %prec UNARY + '*' nonempty_type_quals notype_declarator %prec UNARY { $$ = make_pointer_declarator ($2, $3); } - | '&' nonempty_type_quals notype_declarator1 %prec UNARY + | '&' nonempty_type_quals notype_declarator %prec UNARY { $$ = make_reference_declarator ($2, $3); } - | '*' notype_declarator1 %prec UNARY + | '*' notype_declarator %prec UNARY { $$ = make_pointer_declarator (NULL_TREE, $2); } - | '&' notype_declarator1 %prec UNARY + | '&' notype_declarator %prec UNARY { $$ = make_reference_declarator (NULL_TREE, $2); } - | id_scope '*' type_quals notype_declarator1 - { tree arg = make_pointer_declarator ($3, $4); - if (TREE_CODE ($$) != SCOPE_REF) - $$ = build_push_scope ($$, arg); - else if (TREE_OPERAND ($$, 1) == NULL_TREE) - TREE_OPERAND ($$, 1) = arg; - else - $$ = build_parse_node (SCOPE_REF, $$, arg); + | ptr_to_mem type_quals notype_declarator + { tree arg = make_pointer_declarator ($2, $3); + $$ = build_parse_node (SCOPE_REF, $1, arg); } | direct_notype_declarator ; -complex_notype_declarator1: - '*' nonempty_type_quals notype_declarator1 %prec UNARY +complex_notype_declarator: + '*' nonempty_type_quals notype_declarator %prec UNARY { $$ = make_pointer_declarator ($2, $3); } - | '&' nonempty_type_quals notype_declarator1 %prec UNARY + | '&' nonempty_type_quals notype_declarator %prec UNARY { $$ = make_reference_declarator ($2, $3); } - | '*' complex_notype_declarator1 %prec UNARY + | '*' complex_notype_declarator %prec UNARY { $$ = make_pointer_declarator (NULL_TREE, $2); } - | '&' complex_notype_declarator1 %prec UNARY + | '&' complex_notype_declarator %prec UNARY { $$ = make_reference_declarator (NULL_TREE, $2); } - | id_scope '*' type_quals notype_declarator1 - { tree arg = make_pointer_declarator ($3, $4); - if (TREE_CODE ($$) != SCOPE_REF) - $$ = build_push_scope ($$, arg); - else if (TREE_OPERAND ($$, 1) == NULL_TREE) - TREE_OPERAND ($$, 1) = arg; - else - $$ = build_parse_node (SCOPE_REF, $$, arg); + | ptr_to_mem type_quals notype_declarator + { tree arg = make_pointer_declarator ($2, $3); + $$ = build_parse_node (SCOPE_REF, $1, arg); } | complex_direct_notype_declarator ; @@ -2989,40 +2799,30 @@ complex_direct_notype_declarator: { $$ = build_parse_node (CALL_EXPR, $$, NULL_TREE, NULL_TREE); } | '(' expr_or_declarator ')' { $$ = finish_decl_parsing ($2); } - | '(' complex_notype_declarator1 ')' + | '(' complex_notype_declarator ')' { $$ = $2; } | direct_notype_declarator '[' nonmomentary_expr ']' { $$ = build_parse_node (ARRAY_REF, $$, $3); } | direct_notype_declarator '[' ']' { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); } + ; - /* C++ extensions. */ - | id_scope see_typename notype_unqualified_id - { see_typename (); - if (TREE_CODE ($$) != SCOPE_REF) - $$ = build_push_scope ($$, $3); - else if (TREE_OPERAND ($$, 1) == NULL_TREE) - TREE_OPERAND ($$, 1) = $3; - else - $$ = build_parse_node (SCOPE_REF, $$, $3); - } - | id_scope see_typename TYPENAME - { $$ = build_push_scope ($$, $3); } - | SCOPE see_typename direct_notype_declarator - { $$ = build_parse_node (SCOPE_REF, NULL_TREE, $3); } - | template_type SCOPED_NAME - { tree t; - extern int current_class_depth; +qualified_id: + nested_name_specifier unqualified_id + { got_scope = NULL_TREE; + $$ = build_parse_node (SCOPE_REF, $$, $2); } + ; - t = TREE_TYPE(TREE_OPERAND($2, 0)); - if (t != current_class_type && - TREE_CODE(t) != TEMPLATE_TYPE_PARM) - { - push_nested_class(t, 3); - TREE_COMPLEXITY ($2) = current_class_depth; - } - $$ = $2; - } +notype_qualified_id: + nested_name_specifier notype_unqualified_id + { got_scope = NULL_TREE; + $$ = build_parse_node (SCOPE_REF, $$, $2); } + ; + +overqualified_id: + notype_qualified_id + | global_scope notype_qualified_id + { $$ = $2; } ; functional_cast: @@ -3034,61 +2834,60 @@ functional_cast: { $$ = reparse_absdcl_as_expr ($$, $2); } ; -id_scope: typename_scope - { tree t; - do_id_scope: +type_name: + TYPENAME + | template_type %prec EMPTY + ; - t = resolve_scope_to_name (NULL_TREE, $$); - if (t == NULL_TREE) - { - cp_error ("`%T' is not a valid scope", $$); - $$ = error_mark_node; - } - else - $$ = t; - } +nested_name_specifier: + nested_name_specifier_1 + | nested_name_specifier nested_name_specifier_1 + { $$ = $2; } + ; + +/* Why the @#$%^& do type_name and notype_identifier need to be expanded + inline here?!? (jason) */ +nested_name_specifier_1: + TYPENAME SCOPE + { got_scope = TREE_TYPE ($$); } + | template_type SCOPE + { got_scope = TREE_TYPE ($$); } +/* These break 'const i;' | IDENTIFIER SCOPE - { goto do_id_scope; } - | template_type SCOPE /* try_for_typename %prec EMPTY */ { - if ($$ == error_mark_node) - /* leave it alone */; - else - { - $$ = resolve_scope_to_name (NULL_TREE, TYPE_IDENTIFIER ($$)); - if ($$ == NULL_TREE) - { - error ("undefined explicitly scoped type"); - $$ = error_mark_node; - } - } -/* if ($3) popclass (1); */ + failed_scope: + cp_error ("`%D' is not an aggregate typedef", + lastiddecl ? lastiddecl : $$); + $$ = error_mark_node; } + | PTYPENAME SCOPE + { goto failed_scope; } */ ; -typename_scope: - TYPENAME SCOPE; +complete_type_name: + qualified_type_name + | global_scope qualified_type_name + { $$ = $2; } + ; -scoped_typename: SCOPED_TYPENAME - | template_type SCOPED_TYPENAME - { - /* Kludge!!! See rule "template_type" and the code - * dealing with "template_type_seen_before_scope" in - * yylex(). */ - $$ = $2; - } -/* | template_type SCOPE try_for_typename TYPENAME - { - if ($$ == error_mark_node) - ; - else - { - $$ = build_parse_node (SCOPE_REF, - TYPE_IDENTIFIER ($$), - $4); - } - if ($3) popclass (1); - } */ +complex_type_name: + nested_type + | global_scope qualified_type_name + { $$ = $2; } + ; + +ptr_to_mem: + nested_name_specifier '*' + { got_scope = NULL_TREE; } + | global_scope nested_name_specifier '*' + { $$ = $2; got_scope = NULL_TREE; } + ; + +/* All uses of explicit global scope must go through this nonterminal so + that got_scope will be set before yylex is called to get the next token. */ +global_scope: + SCOPE + { got_scope = void_type_node; } ; /* ANSI new-declarator (5.3.4) */ @@ -3101,23 +2900,13 @@ new_declarator: { $$ = make_reference_declarator ($2, $3); } | '&' type_quals %prec EMPTY { $$ = make_reference_declarator ($2, NULL_TREE); } - | id_scope '*' type_quals %prec EMPTY - { tree arg = make_pointer_declarator ($3, NULL_TREE); - if (TREE_CODE ($$) != SCOPE_REF) - $$ = build_push_scope ($$, arg); - else if (TREE_OPERAND ($$, 1) == NULL_TREE) - TREE_OPERAND ($$, 1) = arg; - else - $$ = build_parse_node (SCOPE_REF, $$, arg); + | ptr_to_mem type_quals %prec EMPTY + { tree arg = make_pointer_declarator ($2, NULL_TREE); + $$ = build_parse_node (SCOPE_REF, $1, arg); } - | id_scope '*' type_quals new_declarator - { tree arg = make_pointer_declarator ($3, $4); - if (TREE_CODE ($$) != SCOPE_REF) - $$ = build_push_scope ($$, arg); - else if (TREE_OPERAND ($$, 1) == NULL_TREE) - TREE_OPERAND ($$, 1) = arg; - else - $$ = build_parse_node (SCOPE_REF, $$, arg); + | ptr_to_mem type_quals new_declarator + { tree arg = make_pointer_declarator ($2, $3); + $$ = build_parse_node (SCOPE_REF, $1, arg); } | direct_new_declarator %prec EMPTY ; @@ -3131,48 +2920,36 @@ direct_new_declarator: ; /* ANSI abstract-declarator (8.1) */ -absdcl1: - '*' nonempty_type_quals absdcl1 +absdcl: + '*' nonempty_type_quals absdcl { $$ = make_pointer_declarator ($2, $3); } - | '*' absdcl1 + | '*' absdcl { $$ = make_pointer_declarator (NULL_TREE, $2); } | '*' type_quals %prec EMPTY { $$ = make_pointer_declarator ($2, NULL_TREE); } - | '&' nonempty_type_quals absdcl1 + | '&' nonempty_type_quals absdcl { $$ = make_reference_declarator ($2, $3); } - | '&' absdcl1 + | '&' absdcl { $$ = make_reference_declarator (NULL_TREE, $2); } | '&' type_quals %prec EMPTY { $$ = make_reference_declarator ($2, NULL_TREE); } - | id_scope '*' type_quals %prec EMPTY - { tree arg = make_pointer_declarator ($3, NULL_TREE); - if (TREE_CODE ($$) != SCOPE_REF) - $$ = build_push_scope ($$, arg); - else if (TREE_OPERAND ($$, 1) == NULL_TREE) - TREE_OPERAND ($$, 1) = arg; - else - $$ = build_parse_node (SCOPE_REF, $$, arg); + | ptr_to_mem type_quals %prec EMPTY + { tree arg = make_pointer_declarator ($2, NULL_TREE); + $$ = build_parse_node (SCOPE_REF, $1, arg); } - | id_scope '*' type_quals absdcl1 - { tree arg = make_pointer_declarator ($3, $4); - if (TREE_CODE ($$) != SCOPE_REF) - $$ = build_push_scope ($$, arg); - else if (TREE_OPERAND ($$, 1) == NULL_TREE) - TREE_OPERAND ($$, 1) = arg; - else - $$ = build_parse_node (SCOPE_REF, $$, arg); + | ptr_to_mem type_quals absdcl + { tree arg = make_pointer_declarator ($2, $3); + $$ = build_parse_node (SCOPE_REF, $1, arg); } | direct_abstract_declarator %prec EMPTY ; /* ANSI direct-abstract-declarator (8.1) */ direct_abstract_declarator: - '(' absdcl1 ')' - { see_typename (); - $$ = $2; } + '(' absdcl ')' + { $$ = $2; } /* `(typedef)1' is `int'. */ | PAREN_STAR_PAREN - { see_typename (); } | direct_abstract_declarator '(' parmlist ')' type_quals %prec '.' { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); } | direct_abstract_declarator LEFT_RIGHT type_quals %prec '.' @@ -3813,11 +3590,6 @@ label_colon: } | PTYPENAME ':' { goto do_label; } - | TYPENAME_COLON - { tree label = define_label (input_filename, lineno, $1); - if (label) - expand_label (label); - } ; try_head: TRY '{' { cplus_expand_start_try (0); } .pushlevel @@ -4160,23 +3932,17 @@ named_parm: /* Here we expand typed_declspecs inline to avoid mis-parsing of TYPESPEC IDENTIFIER. */ typed_declspecs1 declarator - { $$ = build_tree_list ($$, $2); - see_typename (); } + { $$ = build_tree_list ($$, $2); } | typed_typespecs declarator - { $$ = build_tree_list ($$, $2); - see_typename (); } + { $$ = build_tree_list ($$, $2); } | typespec declarator - { $$ = build_tree_list (get_decl_list ($$), $2); - see_typename (); } + { $$ = build_tree_list (get_decl_list ($$), $2); } | typed_declspecs1 absdcl - { $$ = build_tree_list ($$, $2); - see_typename (); } + { $$ = build_tree_list ($$, $2); } | typed_declspecs1 %prec EMPTY - { $$ = build_tree_list ($$, NULL_TREE); - see_typename (); } + { $$ = build_tree_list ($$, NULL_TREE); } | declmods notype_declarator - { $$ = build_tree_list ($$, $2); - see_typename (); } + { $$ = build_tree_list ($$, $2); } ; parm: @@ -4235,13 +4001,10 @@ raise_identifier: { $$ = build_decl_list (NULL_TREE, $$); } | TYPENAME { $$ = build_decl_list (NULL_TREE, $$); } - | SCOPE IDENTIFIER - { $$ = build_decl_list (void_type_node, $2); } - | SCOPE TYPENAME - { $$ = build_decl_list (void_type_node, $2); } - | id_scope IDENTIFIER - { $$ = build_decl_list ($$, $2); } - | scoped_typename + | global_scope IDENTIFIER + { $$ = build_decl_list (NULL_TREE, $2); } + | global_scope TYPENAME + { $$ = build_decl_list (NULL_TREE, $2); } ; ansi_raise_identifier: @@ -4274,87 +4037,87 @@ conversion_declarator: { $$ = make_pointer_declarator ($2, $3); } | '&' type_quals conversion_declarator { $$ = make_reference_declarator ($2, $3); } - | id_scope '*' type_quals conversion_declarator - { tree arg = make_pointer_declarator ($3, $4); - if (TREE_CODE ($$) != SCOPE_REF) - $$ = build_push_scope ($$, arg); - else if (TREE_OPERAND ($$, 1) == NULL_TREE) - TREE_OPERAND ($$, 1) = arg; - else - $$ = build_parse_node (SCOPE_REF, $$, arg); + | ptr_to_mem type_quals conversion_declarator + { tree arg = make_pointer_declarator ($2, $3); + $$ = build_parse_node (SCOPE_REF, $1, arg); } ; +operator: OPERATOR + { got_scope = NULL_TREE; } + ; + operator_name: - OPERATOR '*' + operator '*' { $$ = ansi_opname[MULT_EXPR]; } - | OPERATOR '/' + | operator '/' { $$ = ansi_opname[TRUNC_DIV_EXPR]; } - | OPERATOR '%' + | operator '%' { $$ = ansi_opname[TRUNC_MOD_EXPR]; } - | OPERATOR '+' + | operator '+' { $$ = ansi_opname[PLUS_EXPR]; } - | OPERATOR '-' + | operator '-' { $$ = ansi_opname[MINUS_EXPR]; } - | OPERATOR '&' + | operator '&' { $$ = ansi_opname[BIT_AND_EXPR]; } - | OPERATOR '|' + | operator '|' { $$ = ansi_opname[BIT_IOR_EXPR]; } - | OPERATOR '^' + | operator '^' { $$ = ansi_opname[BIT_XOR_EXPR]; } - | OPERATOR '~' + | operator '~' { $$ = ansi_opname[BIT_NOT_EXPR]; } - | OPERATOR ',' + | operator ',' { $$ = ansi_opname[COMPOUND_EXPR]; } - | OPERATOR ARITHCOMPARE + | operator ARITHCOMPARE { $$ = ansi_opname[$2]; } - | OPERATOR '<' + | operator '<' { $$ = ansi_opname[LT_EXPR]; } - | OPERATOR '>' + | operator '>' { $$ = ansi_opname[GT_EXPR]; } - | OPERATOR EQCOMPARE + | operator EQCOMPARE { $$ = ansi_opname[$2]; } - | OPERATOR ASSIGN + | operator ASSIGN { $$ = ansi_assopname[$2]; } - | OPERATOR '=' + | operator '=' { $$ = ansi_opname [MODIFY_EXPR]; } - | OPERATOR LSHIFT + | operator LSHIFT { $$ = ansi_opname[$2]; } - | OPERATOR RSHIFT + | operator RSHIFT { $$ = ansi_opname[$2]; } - | OPERATOR PLUSPLUS + | operator PLUSPLUS { $$ = ansi_opname[POSTINCREMENT_EXPR]; } - | OPERATOR MINUSMINUS + | operator MINUSMINUS { $$ = ansi_opname[PREDECREMENT_EXPR]; } - | OPERATOR ANDAND + | operator ANDAND { $$ = ansi_opname[TRUTH_ANDIF_EXPR]; } - | OPERATOR OROR + | operator OROR { $$ = ansi_opname[TRUTH_ORIF_EXPR]; } - | OPERATOR '!' + | operator '!' { $$ = ansi_opname[TRUTH_NOT_EXPR]; } - | OPERATOR '?' ':' + | operator '?' ':' { $$ = ansi_opname[COND_EXPR]; } - | OPERATOR MIN_MAX + | operator MIN_MAX { $$ = ansi_opname[$2]; } - | OPERATOR POINTSAT %prec EMPTY + | operator POINTSAT %prec EMPTY { $$ = ansi_opname[COMPONENT_REF]; } - | OPERATOR POINTSAT_STAR %prec EMPTY + | operator POINTSAT_STAR %prec EMPTY { $$ = ansi_opname[MEMBER_REF]; } - | OPERATOR LEFT_RIGHT + | operator LEFT_RIGHT { $$ = ansi_opname[CALL_EXPR]; } - | OPERATOR '[' ']' + | operator '[' ']' { $$ = ansi_opname[ARRAY_REF]; } - | OPERATOR NEW + | operator NEW %prec EMPTY { $$ = ansi_opname[NEW_EXPR]; } - | OPERATOR DELETE + | operator DELETE %prec EMPTY { $$ = ansi_opname[DELETE_EXPR]; } -/* | OPERATOR NEW '[' ']' + | operator NEW '[' ']' { $$ = ansi_opname[VEC_NEW_EXPR]; } - | OPERATOR DELETE '[' ']' - { $$ = ansi_opname[VEC_DELETE_EXPR]; } */ - | OPERATOR typed_typespecs conversion_declarator + | operator DELETE '[' ']' + { $$ = ansi_opname[VEC_DELETE_EXPR]; } + /* Should we be pushing into class scope to parse this? */ + | operator typed_typespecs conversion_declarator { $$ = grokoptypename ($2, $3); } - | OPERATOR error + | operator error { $$ = ansi_opname[ERROR_MARK]; } ; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e9810e117716..ef2fbb28f1ac 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -1690,6 +1690,7 @@ instantiate_template (tmpl, targ_ptr) return fndecl; } +/* classlevel should now never be true. jason 4/12/94 */ void undo_template_name_overload (id, classlevel) tree id; @@ -1711,6 +1712,7 @@ undo_template_name_overload (id, classlevel) #endif } +/* classlevel should now never be true. jason 4/12/94 */ void overload_template_name (id, classlevel) tree id; @@ -1731,12 +1733,9 @@ overload_template_name (id, classlevel) #if 1 /* XXX */ /* This was a botch... names of templates do not get their own private - scopes. Rather, the names of generated template instances should - just get pushed into whatever scope we happen to be in at the moment. - This will typically (but not always) be the global scope. (Maybe - what we really want to do here is a `push_to_toplevel' and then stay - there while we are generating the instance; popping back out to the - current scope when we are done generating the instance.) */ + scopes. Rather, they should go into the binding level already created + by push_template_decls. Except that there isn't one of those for + specializations. */ if (!classlevel) { pushlevel (1); @@ -1765,20 +1764,13 @@ overload_template_name (id, classlevel) if (classlevel) pushdecl_class_level (decl); else -#if 0 /* not yet, should get fixed properly later */ pushdecl (decl); - pushlevel (1); -#else - { - pushdecl (decl); - /* @@ Is this necessary now? */ - IDENTIFIER_LOCAL_VALUE (template) = decl; - } -#endif +#if 0 /* This seems bogus to me; if it isn't, explain why. (jason) */ /* Fake this for now, just to make dwarfout.c happy. It will have to be done in a proper way later on. */ DECL_CONTEXT (decl) = t; +#endif } /* NAME is the IDENTIFIER value of a PRE_PARSED_CLASS_DECL. */ @@ -2028,6 +2020,22 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) return 0; else if (targs[idx]) { + tree t = targs[idx]; + if (TREE_CODE (t) == TREE_CODE (arg)) + switch (TREE_CODE (arg)) + { + case INTEGER_CST: + if (tree_int_cst_equal (t, arg)) + return 0; + break; + case REAL_CST: + if (REAL_VALUES_EQUAL (TREE_REAL_CST (t), TREE_REAL_CST (arg))) + return 0; + break; + /* STRING_CST values are not valid template const parms. */ + default: + ; + } my_friendly_abort (87); return 1; } @@ -2306,3 +2314,18 @@ do_function_instantiation (declspecs, declarator) if (!result) cp_error ("no matching template for `%D' found", decl); } + +tree +create_nested_upt (scope, name) + tree scope, name; +{ + tree t = make_lang_type (UNINSTANTIATED_P_TYPE); + tree d = build_lang_decl (TYPE_DECL, name, t); + + TYPE_NAME (t) = d; + TYPE_VALUES (t) = TYPE_VALUES (scope); + TYPE_CONTEXT (t) = scope; + + pushdecl (d); + return d; +} diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index a259cbe2174d..38e3c77aad79 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -108,10 +108,14 @@ print_lang_type (file, node, indent) else fputs (" X(X&)", file); } - if (TREE_GETS_NEW (node)) - fputs (" gets-new", file); - if (TREE_GETS_DELETE (node)) - fputs (" gets-delete", file); + if (TYPE_GETS_NEW (node) & 1) + fputs (" new", file); + if (TYPE_GETS_NEW (node) & 2) + fputs (" new[]", file); + if (TYPE_GETS_DELETE (node) & 1) + fputs (" delete", file); + if (TYPE_GETS_DELETE (node) & 2) + fputs (" delete[]", file); if (TYPE_HAS_ASSIGNMENT (node)) fputs (" has=", file); if (TYPE_HAS_ASSIGN_REF (node)) diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 984ee439964a..576eaecda903 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1079,16 +1079,16 @@ lookup_field (xbasetype, name, protect, want_type) if (TREE_CODE (rval) == CONST_DECL) { if (this_v == access_private) - errstr = "enum `%s' is a private value of class `%s'"; + errstr = "enum `%D' is a private value of class `%T'"; else if (this_v == access_protected) - errstr = "enum `%s' is a protected value of class `%s'"; + errstr = "enum `%D' is a protected value of class `%T'"; } else { if (this_v == access_private) - errstr = "member `%s' is a private member of class `%s'"; + errstr = "member `%D' is a private member of class `%T'"; else if (this_v == access_protected) - errstr = "member `%s' is a protected member of class `%s'"; + errstr = "member `%D' is a protected member of class `%T'"; } } @@ -1214,7 +1214,7 @@ lookup_field (xbasetype, name, protect, want_type) else { /* This is ambiguous. */ - errstr = "request for member `%s' is ambiguous"; + errstr = "request for member `%D' is ambiguous"; protect = 2; break; } @@ -1250,7 +1250,7 @@ lookup_field (xbasetype, name, protect, want_type) new_v = compute_access (TREE_VALUE (TREE_CHAIN (*tp)), rval); if (this_v != access_default && new_v != this_v) { - errstr = "conflicting access to member `%s'"; + errstr = "conflicting access to member `%D'"; this_v = access_default; } own_access = new_v; @@ -1272,17 +1272,17 @@ lookup_field (xbasetype, name, protect, want_type) if (errstr == 0) { if (own_access == access_private) - errstr = "member `%s' declared private"; + errstr = "member `%D' declared private"; else if (own_access == access_protected) - errstr = "member `%s' declared protected"; + errstr = "member `%D' declared protected"; else if (this_v == access_private) errstr = TREE_PRIVATE (rval) - ? "member `%s' is private" - : "member `%s' is from private base class"; + ? "member `%D' is private" + : "member `%D' is from private base class"; else if (this_v == access_protected) errstr = TREE_PROTECTED (rval) - ? "member `%s' is protected" - : "member `%s' is from protected base class"; + ? "member `%D' is protected" + : "member `%D' is from protected base class"; } if (entry) @@ -1302,17 +1302,7 @@ lookup_field (xbasetype, name, protect, want_type) if (errstr && protect) { - char *p = IDENTIFIER_POINTER (name), *q = NULL; - if (IDENTIFIER_OPNAME_P (name)) - { - q = operator_name_string (name); - p = (char *) xmalloc (9 + strlen (q) + 1); - sprintf (p, "operator %s", q); - } - - error (errstr, p, TYPE_NAME_STRING (type)); - if (q) - free (p); + cp_error (errstr, name, type); rval = error_mark_node; } return rval; @@ -3031,15 +3021,15 @@ push_class_decls (type) search_stack = push_search_level (search_stack, &search_obstack); id = TYPE_IDENTIFIER (type); +#if 0 if (IDENTIFIER_TEMPLATE (id) != 0) { -#if 0 tree tmpl = IDENTIFIER_TEMPLATE (id); push_template_decls (DECL_ARGUMENTS (TREE_PURPOSE (tmpl)), TREE_VALUE (tmpl), 1); -#endif overload_template_name (id, 1); } +#endif /* Push class fields into CLASS_VALUE scope, and mark. */ dfs_walk (TYPE_BINFO (type), dfs_pushdecls, unmarkedp); @@ -3227,3 +3217,27 @@ reinit_search_statistics () n_outer_fields_searched = 0; n_contexts_saved = 0; } + +tree +lookup_nested_tag (type, name) + tree type, name; +{ + tree tags = CLASSTYPE_TAGS (type); + + for (; tags; tags = TREE_CHAIN (tags)) + { + /* The TREE_PURPOSE of an enum tag (which becomes a member of the + enclosing class) is set to the name for the enum type. So, if + name is `bar', and we strike `baz' for `enum bar { baz }', then + this test will be true. */ + if (TREE_PURPOSE (tags) == name) + break; + } + if (tags) + return TYPE_NAME (TREE_VALUE (tags)); + + if (TYPE_CONTEXT (type)) + return lookup_nested_tag (TYPE_CONTEXT (type), name); + + return NULL_TREE; +} diff --git a/gcc/cp/spew.c b/gcc/cp/spew.c index da707eb0848a..b7fc7d573234 100644 --- a/gcc/cp/spew.c +++ b/gcc/cp/spew.c @@ -45,12 +45,6 @@ struct token { }; static int do_aggr (); -static struct token frob_identifier (); -static tree hack_more_ids (); -#if 0 -static struct token hack_scope (); -static tree hack_ptype (); -#endif /* From lex.c: */ /* the declaration found for the last IDENTIFIER token read in. @@ -72,51 +66,10 @@ static unsigned int yylex_ctr = 0; static int debug_yychar (); #endif -#if 0 /* Used by arbitrate_lookup */ -static char follows_typename[END_OF_SAVED_INPUT+1]; -static char follows_identifier[END_OF_SAVED_INPUT+1]; -#endif - -/* This is a hack!!! TEMPLATE_TYPE_SEEN_BEFORE_SCOPE consists of the name - * of the last template_type parsed in parse.y if it is followed by a - * scope operator. It will be reset inside the next invocation of yylex(). - * This is used for recognizing nested types inside templates. - * - niklas@appli.se */ -tree template_type_seen_before_scope; - /* Initialize token_obstack. Called once, from init_lex. */ void init_spew () { -#if 0 /* Used by arbitrate_lookup */ - static char *chars_following_identifier = ".+-|/%^!?:"; - short *ps; - static short toks_follow_ids[] = - { ASSIGN, RANGE, OROR, ANDAND, MIN_MAX, EQCOMPARE, - ARITHCOMPARE, LSHIFT, RSHIFT, UNARY, PLUSPLUS, MINUSMINUS, POINTSAT, - POINTSAT_STAR, DOT_STAR, CONSTANT, STRING, SIZEOF, ENUM, IF, - ELSE, WHILE, DO, FOR, SWITCH, CASE, DEFAULT, BREAK, CONTINUE, - RETURN, GOTO, ASM_KEYWORD, GCC_ASM_KEYWORD, TYPEOF, ALIGNOF, HEADOF, - CLASSOF, SIGOF, ATTRIBUTE, AGGR, VISSPEC, DELETE, RAISE, RERAISE, TRY, - EXCEPT, CATCH, THROW, ANSI_TRY, ANSI_THROW, DYNAMIC_CAST, TYPEID, - EXTERN_LANG_STRING, ALL, END_OF_SAVED_INPUT, -1 }; - static short toks_follow_types[] = - { IDENTIFIER, TYPENAME, SCOPED_TYPENAME, SCOPED_NAME, SCSPEC, - TYPESPEC, TYPE_QUAL, - ELLIPSIS, THIS, OPERATOR, TEMPLATE, SCOPE, START_DECLARATOR, - TYPENAME_COLON, PAREN_STAR_PAREN, TYPENAME_ELLIPSIS, PTYPENAME, - PRE_PARSED_FUNCTION_DECL, PRE_PARSED_CLASS_DECL, -1 }; - - /* Initialize the arrays saying what tokens are definitely - (or possibly) valid following typenames and identifiers. */ - while (*chars_following_identifier) - follows_identifier[*chars_following_identifier++] = 1; - for (ps = toks_follow_ids; *ps != -1; ps++) - follows_identifier[*ps] = 1; - for (ps = toks_follow_types; *ps != -1; ps++) - follows_typename[*ps] = 1; -#endif - gcc_obstack_init(&token_obstack); } @@ -181,7 +134,8 @@ consume_token() : first_token++) #endif -/* Pull in enough tokens from real_yylex that the queue is N long. */ +/* Pull in enough tokens from real_yylex that the queue is N long beyond + the current token. */ static void scan_tokens (n) @@ -278,13 +232,13 @@ probe_obstack (h, obj, nlevels) } /* from lex.c: */ -/* Value is 1 if we should try to make the next identifier look like a - typename (when it may be a local variable or a class variable). - Value is 0 if we treat this name in a default fashion. - Value is -1 if we must not see a type name. */ +/* Value is 1 (or 2) if we should try to make the next identifier look like + a typename (when it may be a local variable or a class variable). + Value is 0 if we treat this name in a default fashion. */ extern int looking_for_typename; extern struct obstack *current_obstack, *saveable_obstack; +tree got_scope; int yylex() @@ -300,36 +254,6 @@ yylex() fprintf(stderr, "\t\t## %d ##",yylex_ctr); } #endif - - /* This is a kludge for recognizing nested types in templates */ - if (template_type_seen_before_scope) - { - shift_tokens (2); /* Sync in hack_more_ids (yes, it's ugly) */ - nth_token (1)->yychar = SCOPE; - yylval.ttype = hack_more_ids (0, template_type_seen_before_scope); - template_type_seen_before_scope = 0; - if (!yylval.ttype) - { - /* Sync back again, leaving SCOPE on the token stream, because we - * failed to substitute the original SCOPE token with a - * SCOPED_TYPENAME. See rule "template_type" in parse.y */ - consume_token (); - } - else - { - tree t = TREE_TYPE(yylval.ttype); - if (TREE_CODE(yylval.ttype) == SCOPE_REF && - t && TREE_CODE(t) == UNINSTANTIATED_P_TYPE) - yychar = SCOPED_NAME; - else - yychar = SCOPED_TYPENAME; -#ifdef SPEW_DEBUG - if (spew_debug) - debug_yychar(yychar); -#endif - return yychar; - } - } /* if we've got tokens, send them */ if (num_tokens()) @@ -370,7 +294,13 @@ yylex() goto retry; case IDENTIFIER: + scan_tokens (1); + if (nth_token (1)->yychar == SCOPE) + /* Don't interfere with the setting from an 'aggr' prefix. */ + looking_for_typename++; + trrr = lookup_name (tmp_token.yylval.ttype, -2); + if (trrr) { tmp_token.yychar = identifier_type (trrr); @@ -378,28 +308,17 @@ yylex() { case TYPENAME: lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype); - if (lastiddecl == NULL_TREE) - lastiddecl = trrr; + if (lastiddecl != trrr) + { + lastiddecl = trrr; + tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr); + } break; case IDENTIFIER: lastiddecl = trrr; break; case PTYPENAME: - /* This is for cases like - template X::operator[] ... - since "X" is (presumably) a PTYPENAME; we might want to - avoid seeing the entire thing as a type name, but X - must be one. - - It might not work right if the thing after the :: - can be a typename nested in X, but I don't think the - PT code would be up to dealing with that anyways. --KR */ - if (looking_for_typename == -1) - { - scan_tokens (2); - if (nth_token(1)->yychar == '<') - looking_for_typename = 0; - } + lastiddecl = NULL_TREE; break; default: my_friendly_abort (101); @@ -410,120 +329,20 @@ yylex() /* and fall through to... */ case TYPENAME: case PTYPENAME: - /* if (new_token) add_token (&tmp_token); */ - *nth_token(0) = tmp_token; - tmp_token = frob_identifier (); - if (looking_for_typename < 0) - { - tmp_token.yychar = IDENTIFIER; - lastiddecl = 0; - looking_for_typename = 0; - } - else if (lastiddecl && TREE_CODE (lastiddecl) == TYPE_DECL) - { - scan_tokens (2); - if (nth_token(0)->yychar == IDENTIFIER - && nth_token (1)->yychar != SCOPE) - looking_for_typename = -1; - else - looking_for_typename = 0; - goto finish_typename_processing; - } - else - looking_for_typename = 0; + consume_token (); + if (looking_for_typename > 0) + looking_for_typename--; break; case SCSPEC: /* do_aggr needs to check if the previous token was RID_FRIEND, so just increment first_token instead of calling consume_token. */ first_token++; - goto finish_typename_processing; + break; case TYPESPEC: consume_token (); - finish_typename_processing: -#if 0 - /* Now see if we should insert a START_DECLARATOR token. - Here are the cases caught: - - typespec ( * ID ) ( // ptr to function - typespec ( & ID ) ( // ref to function - typespec ( * ID ) [ // array of pointers - typespec ( & ID ) [ // array of references - - This is a terrible kludge. */ - - scan_tokens (2); - if (nth_token (0)->yychar == '(' - && (nth_token (1)->yychar == '*' - || nth_token (1)->yychar == '&')) - { - scan_tokens (5); - if (nth_token (3)->yychar == ')' - && (nth_token (4)->yychar == '(' - || nth_token (4)->yychar == '[' - || nth_token (4)->yychar == LEFT_RIGHT) - && (nth_token (2)->yychar == IDENTIFIER - || nth_token (2)->yychar == TYPENAME)) - { - shift_tokens (1); - nth_token (0)->yychar = START_DECLARATOR; - } - } - /* Extend to handle: - - typespec (ID::* qf)( // ptr to member function - typespec (ID::* qf)[ // array of ptr to member functions - - */ - if (nth_token (0)->yychar == '(' - && (nth_token (1)->yychar == IDENTIFIER - || nth_token (1)->yychar == TYPENAME)) - { - scan_tokens (7); - if (nth_token (2)->yychar == SCOPE - && nth_token (3)->yychar == '*' - && (nth_token (4)->yychar == IDENTIFIER - || nth_token (4)->yychar == TYPENAME) - && nth_token (5)->yychar == ')' - && (nth_token (6)->yychar == '(' - || nth_token (6)->yychar == '[' - || nth_token (6)->yychar == LEFT_RIGHT)) - { - shift_tokens (1); - nth_token (0)->yychar = START_DECLARATOR; - } - } -#endif break; -#if 0 - case '(': - /* Handle casts. We are looking for one of: - `( TYPENAME' followed by `)', or - `( TYPENAME *' followed by one of `[,*,&,)', or - `( TYPENAME &' followed by one of `[,*,&,)', or - `( TYPENAME [' followed by `]'. We are punting - generality on scanning casts to array types. */ - scan_tokens (4); - if (nth_token (1)->yychar == IDENTIFIER) - { - tree type = identifier_typedecl_value (nth_token (1)->yylval.ttype); - if (type) - switch (nth_token (2)->yychar) - { - default: - break; - } - } - break; - - case SCOPE: - /* if (new_token) add_token (&tmp_token); */ - *nth_token(0) = tmp_token; - tmp_token = hack_scope (); - break; -#endif - case AGGR: *nth_token(0) = tmp_token; do_aggr (); @@ -533,36 +352,7 @@ yylex() looking_for_typename = 1; /* fall through... */ default: -#ifdef SPEW_DEBUG - if (spew_debug) - debug_yychar(tmp_token.yychar); -#endif consume_token(); - yylval = tmp_token.yylval; - yychar = tmp_token.yychar; - end_of_file = tmp_token.end_of_file; - return tmp_token.yychar; - } - - if (tmp_token.yychar == SCOPED_TYPENAME) - { -#if 0 - tree t2 = resolve_scope_to_name (NULL_TREE, tmp_token.yylval.ttype); - if (t2 != NULL_TREE) - { - tmp_token.yylval.ttype = t2; - tmp_token.yychar = TYPENAME; - } - else - { - /* unwind? */ - } - } - else - { - /* couldn't get here, as is... */ -#endif - tmp_token.yychar = TYPENAME; } yylval = tmp_token.yylval; @@ -572,7 +362,6 @@ yylex() if (spew_debug) debug_yychar(yychar); #endif -/* consume_token(); */ /* already eaten by frob_identifier?... */ return yychar; } @@ -618,515 +407,6 @@ do_aggr () } return 0; } - -static struct token -frob_identifier () -{ - /* we could have a type, if it is followed by :: (if so, suck it all up); */ - /* we could have a ptypename; */ - /* we could have a normal identifier. */ - tree t1; - struct token rt; - - scan_tokens(1); - rt = *nth_token(0); - -#if 0 - if (nth_token(1)->yychar == '<') - { - t1 = hack_ptype(); /* suck up the whole thing */ - if (t1) - { - rt.yylval.ttype = t1; - rt.yychar = TYPENAME; - *nth_token(0) = rt; - } - /* else fall out bottom */ - } -#endif - - if (nth_token(1)->yychar == SCOPE) - { -#if 0 - t1 = hack_more_ids(0); - if (t1 && TREE_CODE(t1) == SCOPE_REF) -#else - t1 = hack_more_ids(0, nth_token (0)->yylval.ttype); - if (t1) -#endif - { - rt.yylval.ttype = t1; - rt.yychar = SCOPED_TYPENAME ; - return rt; - } - else - { - /* deal with types (enums?) in classes... */ - struct token *tok; - tree ta, tb; - scan_tokens(3); - - /* Have to check for a type conversion operator - to a nested type. */ - if (nth_token (2)->yychar == OPERATOR) - tok = nth_token (3); - else - tok = nth_token(2); - - if (tok->yychar == IDENTIFIER || tok->yychar == TYPENAME) - { - ta = build_parse_node (SCOPE_REF, - nth_token(0)->yylval.ttype, - tok->yylval.ttype); - tb = resolve_scope_to_name (NULL_TREE, ta); - - if (tb != NULL_TREE) - { - if (nth_token (2)->yychar == OPERATOR) - { - /* Have to keep these tokens around - so we can finish parsing the declaration. - What do we do for - - int foo::operator bar::baz (); - - where bar is a nested class in foo? */ - nth_token (3)->yychar = TYPENAME; - nth_token (3)->yylval.ttype = tb; - } - else - { - consume_token (); /* base type */ - consume_token (); /* SCOPE */ - consume_token (); /* member type */ - rt.yychar = TYPENAME; - rt.yylval.ttype = tb; - rt.end_of_file = tok->end_of_file; - return rt; - } - - } - } - /* else fall out bottom */ - } - } - - consume_token(); - return rt; -} - -#if 0 -/* When this function is called, nth_token(0) is the current - token we are scanning. This means that the next token we'll - scan is nth_token (1). Usually the next token we'll scan - is nth_token (0) (and the current token is in [yylval,yychar]). */ -tree -arbitrate_lookup (name, exp_decl, type_decl) - tree name, exp_decl, type_decl; -{ - int ch; - tree t; - char *assume; - - scan_tokens (3); - ch = nth_token (1)->yychar; - - switch (ch) - { - case '(': - case LEFT_RIGHT: - /* If we guessed wrong here, `build_functional_cast' can fix it. */ - return type_decl; - - case '=': - if (global_bindings_p ()) - /* Probably a default parameter. */ - return type_decl; - /* Probably not an initialization. */ - return exp_decl; - - case '[': - /* This needs special help because an expression inside the - brackets means nothing. */ - { - int i; - - for (i = 0; i < 42; i++) - { - int ith_yychar; - - scan_tokens (3+i); - ith_yychar = nth_token (2+i)->yychar; - - /* If we hit an undefined identifier, assume - the decl in arbitration is its type specifier. */ - if (ith_yychar == IDENTIFIER - && lookup_name (nth_token (2+i)->yylval.ttype, 0) == 0) - return type_decl; - else if (ith_yychar == ']') - { - /* There are only a few things we expect after a ']' - in a declarator. */ - i += 1; - scan_tokens (4+i); - ith_yychar = nth_token (2+i)->yychar; - - /* These are inconclusive. */ - if (ith_yychar == LEFT_RIGHT - || ith_yychar == '(' - || ith_yychar == '[' - || ith_yychar == ',') - continue; - /* stmt or decl? We'll probably never know. */ - else if (ith_yychar == ';') - goto warn_ambiguous; - - if (ith_yychar == '=') - { - if (nth_token (3+i)->yychar == '{') - return type_decl; - continue; - } - - /* Whatever it is, it looks like we're processing an expr. */ - return exp_decl; - } - } - goto warn_ambiguous; - } - - case ',': - case ';': - case '&': - case '<': - case '*': - case ']': - case ')': - case '>': - /* see if the next token looks like it wants to be part - of a declaration list or an expression list. */ - { - int i; - - /* Some heuristics: if we are inside a function definition, - prefer the local declaration. */ - if (! global_bindings_p ()) - { - if (IDENTIFIER_LOCAL_VALUE (name) == exp_decl) - return exp_decl; - if (IDENTIFIER_LOCAL_VALUE (name) != type_decl - && IDENTIFIER_CLASS_VALUE (name) == exp_decl) - return exp_decl; - } - /* If these symbols follow in a list, we know it's a list of - expressions. */ - if (follows_identifier[nth_token (2)->yychar]) - return exp_decl; - - /* If we see a id&, or id&) the we are probably in an argument list. */ - if (ch=='&' - && (nth_token (2)->yychar == ',' || nth_token (2)->yychar == ')')) - return type_decl; - - /* Look for the first identifier or other distinguishing token - we find in the next several tokens. */ - for (i = 0; i < 42; i++) - { - int ith_yychar; - - scan_tokens (3+i); - ith_yychar = nth_token (2+i)->yychar; - - if (ith_yychar == IDENTIFIER) - { - tree as_type = lookup_name (nth_token (2+i)->yylval.ttype, 1); - if (as_type && TREE_CODE (as_type) != TYPE_DECL) - return exp_decl; - /* An undeclared identifier or a typename means we're - probably looking at a typename. */ - return type_decl; - } - else if (ith_yychar == EMPTY - || follows_identifier[ith_yychar]) - return exp_decl; - else if (follows_typename[ith_yychar]) - return type_decl; - /* stmt or decl? We'll probably never know. */ - else if (ith_yychar == ';') - goto warn_ambiguous; - } - goto warn_ambiguous; - } - - default: - if (follows_identifier[ch]) - return exp_decl; - if (follows_typename[ch]) - return type_decl; - - /* Fall through... */ - warn_ambiguous: - if (ch == '[') - { - assume = "expression"; - t = exp_decl; - } - else - { - assume = "type"; - t = type_decl; - } - - warning ("name `%s' could be type or expression; compiler assuming %s", - IDENTIFIER_POINTER (DECL_NAME (t)), assume); - return t; - } -} -#endif - -/* now returns decl_node */ - -#if 0 -static tree -hack_ptype() -{ - /* when we get here, we know that [0] is a ptype and [1] is '<'. - * now we loop over simple parameters. */ - struct token this_param; - int n = 2; - tree tplist = 0; - tree tc; - scan_tokens(n+1); - - while((this_param = *nth_token(n)).yychar != '>') - { - /* if it is a type, add it to the list */ - tree thistype; - - switch(this_param.yychar) - { - case IDENTIFIER: - case TYPENAME: - case TYPESPEC: - break; - default: - return 0; - } - - thistype = this_param.yylval.ttype; - thistype = lookup_name(thistype, 1); - thistype = TREE_TYPE (thistype); - - if (tplist) - tplist = chainon (tplist, build_tree_list (NULL_TREE, thistype)); - else - tplist = build_tree_list(NULL_TREE, thistype); - - - /* then suck up the comma */ - n++; - scan_tokens(n+1); - this_param = *nth_token(n); - if (this_param.yychar == ',') - { - n++; - scan_tokens(n+1); - continue; - } - if (this_param.yychar == '>') - break; - return 0; - } - - /* once we're done, lookup_template_class -> identifier */ - tc = lookup_template_class (nth_token(0)->yylval.ttype,tplist); - /* then lookup_name on that to get a type, if there is one */ - tc = lookup_name (tc, 1); - if (tc) - { - int i; - /* don't actually eat the trailing '>'... we can replace it! */ - for (i=0; iyychar; - if (tmp_y == IDENTIFIER || tmp_y == TYPENAME) - { - scan_tokens(n+2+2); - if (nth_token(n+1)->yychar == SCOPE) - { - if (nth_token(n+1+2)->yychar == SCOPE) - { - tree hmi; - - consume_token(); /* last IDENTIFIER (this_iter) */ - consume_token(); /* last SCOPE */ - this2_iter = *nth_token(n); - - hmi = hack_more_ids (n); - - if (hmi) - return build_parse_node (SCOPE_REF, this_iter.yylval.ttype, hmi); - consume_token(); /* last IDENTIFIER (this2_iter) */ - return build_parse_node (SCOPE_REF, this_iter.yylval.ttype, - this2_iter.yylval.ttype); - } - else - { - /* consume_token(); */ /* last IDENTIFIER */ - /* leave whatever else we got */ - /* return this_iter.yylval.ttype; */ - return NULL_TREE; - } - } - } - return NULL_TREE; /* @@ may need to backtrack */ -} -#else -/* niklas@appli.se says: I didn't understand how the code above was intended - * to work, so I rewrote it (also changed the interface a bit). This code - * dives down an IDENTIFIER/TYPENAME SCOPE ... chain as long as the parsed - * type prefix constitutes recognizable (by resolve_scope_to_name) types. - * Interface changed like this: - * 1. Takes an extra argument containing the name of the the type recognized - * so far. - * 2. Now returns the name of the type instead of a SCOPE_REF. */ -static tree -hack_more_ids(n, outer) - int n; - tree outer; -{ - int ch; - tree type, val, inner, outer_t; - - scan_tokens (n + 2); - if (nth_token (n + 1)->yychar != SCOPE - || ((ch = nth_token (n + 2)->yychar) != IDENTIFIER && ch != TYPENAME)) - return NULL_TREE; - - inner = nth_token(n+2)->yylval.ttype; - val = build_parse_node (SCOPE_REF, outer, inner); - outer_t = TREE_TYPE(outer); - if (outer_t && TREE_CODE(outer_t) == UNINSTANTIATED_P_TYPE) - { - tree t = make_lang_type (UNINSTANTIATED_P_TYPE); - tree id = inner; - tree d = build_lang_decl (TYPE_DECL, id, t); - - TYPE_NAME (t) = d; - TYPE_VALUES (t) = TYPE_VALUES(outer_t); - TYPE_CONTEXT(t) = outer_t; -/* - pushdecl_top_level (d); -*/ - pushdecl(d); - - type = val; - TREE_TYPE(type) = t; - } - else - { - type = resolve_scope_to_name (NULL_TREE, val); - if (type == NULL_TREE) - return NULL_TREE; - } - consume_token (); - consume_token (); - val = hack_more_ids (n, type); - if (! val) - consume_token (); - return val ? val : type; -} -#endif - -#if 0 -static struct token -hack_scope () -{ - /* we've got a :: - what follows is either a global var or a type. */ - /* hmm, template names can be in the global scope too... */ - tree t1; - struct token rt; - - scan_tokens(1); - if (nth_token(1)->yychar == IDENTIFIER) - { - /* @@ this is probably not right, but doesn't get hit yet */ - t1 = build_parse_node (SCOPE_REF, - NULL_TREE, /* to get "global" scope */ - hack_more_ids(0)); /* do some prefetching */ - rt.yylval.ttype = t1; - rt.yychar = /*SCOPED_*/TYPENAME; - return rt; - } - else - { - rt = *nth_token(0); - consume_token(); - return rt; - } -} -#endif - -/* - * Generations: - * - * PINST: PTYPE { saved_arg_count = arg_count($1) } - * '<' { arg_c = 0; } PARGS '>' - * ; - * PARG: TYPE - * | VALUE - * ; - * (of course the arg counting doesn't work for recursion... Do it right.) - * PARGS: PARG { assert(arg_c == saved_arg_count); } - * | PARG ',' PARGS { arg_c++; } - * ; - * ATYPE: PINST - * | TYPEID - * ; - * TYPE: ATYPE - * | ATYPE { basetype = $1; } '::' TYPEKIDS - * ; - * TYPEKIDS: TYPE { assert ($1 is a member of basetype); } - * | TYPEKIDS { basetype += $1} TYPE { assert( $3 is in basetype ); } - * ; - * - * - * state0: ; ATYPE - * TYPE '<': ac = args($0), base = CALL state1, state3 - * TYPE '::': base=$0, state3 - * else return TYPE - * state1: ; begin PARGS - * if(ac < list length) punt - * PARG ",": add to list, state1 - * PARG ">": add to list, return - * else unravel - * state3: ; begin TYPEKIDS - * TYPE: - */ - #ifdef SPEW_DEBUG /* debug_yychar takes a yychar (token number) value and prints its name. */