Commit a28e3c7f by Mike Stump

32nd Cygnus<->FSF merge

From-SVN: r7047
parent 7062b881
...@@ -200,7 +200,7 @@ parse.o : $(srcdir)/parse.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h lex.h ...@@ -200,7 +200,7 @@ parse.o : $(srcdir)/parse.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h lex.h
`echo $(srcdir)/parse.c | sed 's,^\./,,'` `echo $(srcdir)/parse.c | sed 's,^\./,,'`
$(srcdir)/parse.c $(srcdir)/parse.h : $(srcdir)/parse.y $(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); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y
cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h
......
...@@ -2673,10 +2673,7 @@ build_scoped_method_call (exp, scopes, name, parms) ...@@ -2673,10 +2673,7 @@ build_scoped_method_call (exp, scopes, name, parms)
{ {
/* Explicit call to destructor. */ /* Explicit call to destructor. */
name = TREE_OPERAND (name, 0); name = TREE_OPERAND (name, 0);
if (TREE_TYPE (decl) != if (name != constructor_name (TREE_TYPE (decl)))
(IDENTIFIER_CLASS_VALUE (name)
? IDENTIFIER_CLASS_TYPE_VALUE (name)
: IDENTIFIER_TYPE_VALUE (name)))
{ {
cp_error cp_error
("qualified type `%T' does not match destructor type `%T'", ("qualified type `%T' does not match destructor type `%T'",
...@@ -2808,6 +2805,10 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2808,6 +2805,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
/* If it doesn't work, two argument delete must work */ /* If it doesn't work, two argument delete must work */
TREE_CHAIN (parms) = save_last; 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) if (TREE_CODE (name) == BIT_NOT_EXPR)
{ {
......
...@@ -2494,7 +2494,9 @@ finish_struct_methods (t, fn_fields, nonprivate_method) ...@@ -2494,7 +2494,9 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
for (x = *testp; x; x = DECL_CHAIN (x)) 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 */ /* ANSI C++ June 5 1992 WP 12.5.5.1 */
cp_error_at ("`%D' overloaded", fn_fields); cp_error_at ("`%D' overloaded", fn_fields);
...@@ -4149,8 +4151,10 @@ finish_struct (t, list_of_fieldlists, warn_anon) ...@@ -4149,8 +4151,10 @@ finish_struct (t, list_of_fieldlists, warn_anon)
else if (flag_dossier && ! CLASSTYPE_DOSSIER (t)) else if (flag_dossier && ! CLASSTYPE_DOSSIER (t))
build_t_desc (t, 1); build_t_desc (t, 1);
#if 0
if (TYPE_NAME (t) && TYPE_IDENTIFIER (t)) if (TYPE_NAME (t) && TYPE_IDENTIFIER (t))
undo_template_name_overload (TYPE_IDENTIFIER (t), 1); undo_template_name_overload (TYPE_IDENTIFIER (t), 1);
#endif
if (current_class_type) if (current_class_type)
popclass (0); popclass (0);
else else
...@@ -4426,10 +4430,7 @@ pushclass (type, modify) ...@@ -4426,10 +4430,7 @@ pushclass (type, modify)
current_function_decl = NULL_TREE; current_function_decl = NULL_TREE;
if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE) if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
{ declare_uninstantiated_type_level ();
declare_uninstantiated_type_level ();
overload_template_name (current_class_name, 0);
}
else if (type != previous_class_type || current_class_depth > 1) else if (type != previous_class_type || current_class_depth > 1)
{ {
build_mi_matrix (type); build_mi_matrix (type);
...@@ -4457,6 +4458,9 @@ pushclass (type, modify) ...@@ -4457,6 +4458,9 @@ pushclass (type, modify)
unuse_fields (type); 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)) for (tags = CLASSTYPE_TAGS (type); tags; tags = TREE_CHAIN (tags))
{ {
TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 1; TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 1;
...@@ -4513,9 +4517,9 @@ popclass (modify) ...@@ -4513,9 +4517,9 @@ popclass (modify)
TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0; TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0;
tags = TREE_CHAIN (tags); 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 (); poplevel_class ();
...@@ -4583,7 +4587,12 @@ push_nested_class (type, modify) ...@@ -4583,7 +4587,12 @@ push_nested_class (type, modify)
tree type; tree type;
int modify; 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) if (context && TREE_CODE (context) == RECORD_TYPE)
push_nested_class (context, 2); push_nested_class (context, 2);
......
...@@ -32,6 +32,7 @@ DEFTREECODE (CP_OFFSET_REF, "cp_offset_ref", "r", 2) ...@@ -32,6 +32,7 @@ DEFTREECODE (CP_OFFSET_REF, "cp_offset_ref", "r", 2)
Operand 1 is the value to pass to the destroying function Operand 1 is the value to pass to the destroying function
saying whether the store should be deallocated as well. */ saying whether the store should be deallocated as well. */
DEFTREECODE (DELETE_EXPR, "dl_expr", "e", 2) DEFTREECODE (DELETE_EXPR, "dl_expr", "e", 2)
DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", "e", 2)
/* Value is reference to particular overloaded class method. /* Value is reference to particular overloaded class method.
Operand 0 is the class name (an IDENTIFIER_NODE); Operand 0 is the class name (an IDENTIFIER_NODE);
...@@ -52,6 +53,7 @@ DEFTREECODE (TYPE_EXPR, "type_expr", "e", 1) ...@@ -52,6 +53,7 @@ DEFTREECODE (TYPE_EXPR, "type_expr", "e", 1)
operand 1 is argument list to initialization function, operand 1 is argument list to initialization function,
and operand 2 is the slot which was allocated for this expression. */ and operand 2 is the slot which was allocated for this expression. */
DEFTREECODE (NEW_EXPR, "nw_expr", "e", 3) 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 /* Distinguish variables that are only used to identify exceptions
that were caught. Only the DECL_NAME (and TREE_CHAIN) that were caught. Only the DECL_NAME (and TREE_CHAIN)
......
...@@ -68,10 +68,6 @@ struct lang_id2 ...@@ -68,10 +68,6 @@ struct lang_id2
#define IDENTIFIER_TYPE_VALUE(NODE) (TREE_TYPE (NODE)) #define IDENTIFIER_TYPE_VALUE(NODE) (TREE_TYPE (NODE))
#define SET_IDENTIFIER_TYPE_VALUE(NODE,TYPE) (TREE_TYPE (NODE) = TYPE) #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_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) \ #define LANG_ID_FIELD(NAME,NODE) \
(((struct lang_identifier *)(NODE))->x \ (((struct lang_identifier *)(NODE))->x \
...@@ -325,7 +321,7 @@ enum languages { lang_c, lang_cplusplus }; ...@@ -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 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(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) \ #define IS_AGGR_TYPE_2(TYPE1,TYPE2) \
(TREE_CODE (TYPE1) == TREE_CODE (TYPE2) \ (TREE_CODE (TYPE1) == TREE_CODE (TYPE2) \
&& IS_AGGR_TYPE (TYPE1)&IS_AGGR_TYPE (TYPE2)) && IS_AGGR_TYPE (TYPE1)&IS_AGGR_TYPE (TYPE2))
...@@ -395,14 +391,13 @@ struct lang_type ...@@ -395,14 +391,13 @@ struct lang_type
unsigned vtable_needs_writing : 1; unsigned vtable_needs_writing : 1;
unsigned has_assign_ref : 1; unsigned has_assign_ref : 1;
unsigned gets_new : 1; unsigned gets_new : 2;
unsigned gets_placed_new : 1; unsigned gets_delete : 2;
unsigned gets_delete : 1;
unsigned has_call_overloaded : 1; unsigned has_call_overloaded : 1;
unsigned has_array_ref_overloaded : 1; unsigned has_array_ref_overloaded : 1;
unsigned has_arrow_overloaded : 1; unsigned has_arrow_overloaded : 1;
unsigned local_typedecls : 1;
unsigned local_typedecls : 1;
unsigned interface_only : 1; unsigned interface_only : 1;
unsigned interface_unknown : 1; unsigned interface_unknown : 1;
unsigned needs_virtual_reinit : 1; unsigned needs_virtual_reinit : 1;
...@@ -410,16 +405,16 @@ struct lang_type ...@@ -410,16 +405,16 @@ struct lang_type
unsigned declared_class : 1; unsigned declared_class : 1;
unsigned being_defined : 1; unsigned being_defined : 1;
unsigned redefined : 1; unsigned redefined : 1;
unsigned no_globalize : 1;
unsigned no_globalize : 1;
unsigned marked : 1; unsigned marked : 1;
unsigned marked2 : 1; unsigned marked2 : 1;
unsigned marked3 : 1; unsigned marked3 : 1;
unsigned marked4 : 1; unsigned marked4 : 1;
unsigned marked5 : 1; unsigned marked5 : 1;
unsigned marked6 : 1; unsigned marked6 : 1;
unsigned use_template : 2;
unsigned use_template : 2;
unsigned debug_requested : 1; unsigned debug_requested : 1;
unsigned has_method_call_overloaded : 1; unsigned has_method_call_overloaded : 1;
unsigned private_attr : 1; unsigned private_attr : 1;
...@@ -427,8 +422,8 @@ struct lang_type ...@@ -427,8 +422,8 @@ struct lang_type
unsigned ptrmemfunc_flag : 1; unsigned ptrmemfunc_flag : 1;
unsigned is_signature : 1; unsigned is_signature : 1;
unsigned is_signature_pointer : 1; unsigned is_signature_pointer : 1;
unsigned is_signature_reference : 1;
unsigned is_signature_reference : 1;
unsigned has_default_implementation : 1; unsigned has_default_implementation : 1;
unsigned grokking_typedef : 1; unsigned grokking_typedef : 1;
unsigned has_opaque_typedecls : 1; unsigned has_opaque_typedecls : 1;
...@@ -436,15 +431,16 @@ struct lang_type ...@@ -436,15 +431,16 @@ struct lang_type
unsigned was_anonymous : 1; unsigned was_anonymous : 1;
unsigned has_real_assignment : 1; unsigned has_real_assignment : 1;
unsigned has_real_assign_ref : 1; unsigned has_real_assign_ref : 1;
unsigned has_const_init_ref : 1; unsigned has_const_init_ref : 1;
unsigned has_complex_init_ref : 1; unsigned has_complex_init_ref : 1;
unsigned has_complex_assign_ref : 1; unsigned has_complex_assign_ref : 1;
unsigned vec_delete_takes_size : 1;
/* The MIPS compiler gets it wrong if this struct also /* The MIPS compiler gets it wrong if this struct also
does not fill out to a multiple of 4 bytes. Add a does not fill out to a multiple of 4 bytes. Add a
member `dummy' with new bits if you go over the edge. */ member `dummy' with new bits if you go over the edge. */
unsigned dummy : 22; unsigned dummy : 20;
unsigned n_vancestors : 16; unsigned n_vancestors : 16;
} type_flags; } type_flags;
...@@ -519,9 +515,17 @@ struct lang_type ...@@ -519,9 +515,17 @@ struct lang_type
/* Nonzero for _CLASSTYPE means that operator new and delete are defined, /* Nonzero for _CLASSTYPE means that operator new and delete are defined,
respectively. */ respectively. */
#define TREE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_new) #define TYPE_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 TYPE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_delete)
#define TREE_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. */ /* Nonzero for TREE_LIST or _TYPE node means that this node is class-local. */
#define TREE_NONLOCAL_FLAG(NODE) (TREE_LANG_FLAG_0 (NODE)) #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)); ...@@ -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_x_delete PROTO((tree, tree, int, tree));
extern tree build_delete PROTO((tree, tree, tree, int, int)); extern tree build_delete PROTO((tree, tree, tree, int, int));
extern tree build_vbase_delete PROTO((tree, tree)); 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 */ /* in input.c */
...@@ -2081,6 +2085,7 @@ extern int do_pending_expansions PROTO((void)); ...@@ -2081,6 +2085,7 @@ extern int do_pending_expansions PROTO((void));
extern void do_pending_templates PROTO((void)); extern void do_pending_templates PROTO((void));
struct tinst_level *tinst_for_decl PROTO((void)); struct tinst_level *tinst_for_decl PROTO((void));
extern void do_function_instantiation PROTO((tree, tree)); extern void do_function_instantiation PROTO((tree, tree));
extern tree create_nested_upt PROTO((tree, tree));
/* in search.c */ /* in search.c */
extern tree make_memoized_table_entry PROTO((tree, tree, int)); extern tree make_memoized_table_entry PROTO((tree, tree, int));
...@@ -2092,6 +2097,7 @@ extern enum access_type compute_access PROTO((tree, tree)); ...@@ -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_field PROTO((tree, tree, int, int));
extern tree lookup_nested_field PROTO((tree, int)); extern tree lookup_nested_field PROTO((tree, int));
extern tree lookup_fnfields PROTO((tree, 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 HOST_WIDE_INT breadth_first_search PROTO((tree, int (*)(), int (*)()));
extern int tree_needs_constructor_p PROTO((tree, int)); extern int tree_needs_constructor_p PROTO((tree, int));
extern int tree_has_any_destructor_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)); ...@@ -2193,6 +2199,7 @@ extern int comp_target_types PROTO((tree, tree, int));
extern tree common_base_types PROTO((tree, tree)); extern tree common_base_types PROTO((tree, tree));
extern int compparms PROTO((tree, tree, int)); extern int compparms PROTO((tree, tree, int));
extern int comp_target_types 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 unsigned_type PROTO((tree));
extern tree signed_type PROTO((tree)); extern tree signed_type PROTO((tree));
extern tree signed_or_unsigned_type PROTO((int, tree)); extern tree signed_or_unsigned_type PROTO((int, tree));
......
...@@ -720,8 +720,16 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum, ...@@ -720,8 +720,16 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
{ {
/* When casting an lvalue to a reference type, just convert into /* When casting an lvalue to a reference type, just convert into
a pointer to the new type and deference it. This is allowed 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 */ 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); rval = build_unary_op (ADDR_EXPR, expr, 0);
if (rval != error_mark_node) if (rval != error_mark_node)
rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval); rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval);
...@@ -744,6 +752,7 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum, ...@@ -744,6 +752,7 @@ convert_to_reference (decl, reftype, expr, fndecl, parmnum,
/* Definitely need to go through a constructor here. */ /* Definitely need to go through a constructor here. */
if (TYPE_HAS_CONSTRUCTOR (type) if (TYPE_HAS_CONSTRUCTOR (type)
&& ! CLASSTYPE_ABSTRACT_VIRTUALS (type)
&& (rval = build_method_call && (rval = build_method_call
(NULL_TREE, constructor_name_full (type), (NULL_TREE, constructor_name_full (type),
build_tree_list (NULL_TREE, expr), TYPE_BINFO (type), build_tree_list (NULL_TREE, expr), TYPE_BINFO (type),
......
...@@ -1964,7 +1964,8 @@ decls_match (newdecl, olddecl) ...@@ -1964,7 +1964,8 @@ decls_match (newdecl, olddecl)
{ {
int types_match; 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 f1 = TREE_TYPE (newdecl);
tree f2 = TREE_TYPE (olddecl); tree f2 = TREE_TYPE (olddecl);
...@@ -1997,10 +1998,19 @@ decls_match (newdecl, olddecl) ...@@ -1997,10 +1998,19 @@ decls_match (newdecl, olddecl)
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (f1)), if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (f1)),
TYPE_MAIN_VARIANT (TREE_TYPE (f2)), 2)) TYPE_MAIN_VARIANT (TREE_TYPE (f2)), 2))
{ {
if (DECL_LANGUAGE (olddecl) == lang_c if (! strict_prototypes_lang_c && DECL_LANGUAGE (olddecl) == lang_c
&& ! strict_prototypes_lang_c
&& p2 == NULL_TREE) && 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 else
types_match = compparms (p1, p2, 1); types_match = compparms (p1, p2, 1);
} }
...@@ -2249,12 +2259,7 @@ duplicate_decls (newdecl, olddecl) ...@@ -2249,12 +2259,7 @@ duplicate_decls (newdecl, olddecl)
int foo () { bar (); } int foo () { bar (); }
is OK. */ is OK. */
if (current_lang_stack == current_lang_base) if (current_lang_stack == current_lang_base)
{ DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl);
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);
}
else else
{ {
cp_error_at ("previous declaration of `%#D' with %L linkage", cp_error_at ("previous declaration of `%#D' with %L linkage",
...@@ -2268,7 +2273,8 @@ duplicate_decls (newdecl, olddecl) ...@@ -2268,7 +2273,8 @@ duplicate_decls (newdecl, olddecl)
if (pedantic if (pedantic
&& (TREE_READONLY (newdecl) != TREE_READONLY (olddecl) && (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)
|| TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (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, /* If new decl is `static' and an `extern' was seen previously,
...@@ -2318,7 +2324,8 @@ duplicate_decls (newdecl, olddecl) ...@@ -2318,7 +2324,8 @@ duplicate_decls (newdecl, olddecl)
} Thing; } Thing;
*/ */
#if 0 #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 #endif
} }
...@@ -2363,9 +2370,10 @@ duplicate_decls (newdecl, olddecl) ...@@ -2363,9 +2370,10 @@ duplicate_decls (newdecl, olddecl)
TREE_TYPE (olddecl) = build_exception_variant (ctype, newtype, TREE_TYPE (olddecl) = build_exception_variant (ctype, newtype,
TYPE_RAISES_EXCEPTIONS (oldtype)); 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); cp_error_at ("...from previous declaration here", olddecl);
} }
} }
...@@ -2683,7 +2691,8 @@ pushdecl (x) ...@@ -2683,7 +2691,8 @@ pushdecl (x)
if (extra_warnings) 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, warning_with_file_and_line (file, line,
"previous declaration of `%s'", "previous declaration of `%s'",
decl_as_string (t, 0)); decl_as_string (t, 0));
...@@ -3176,8 +3185,11 @@ push_overloaded_decl (decl, forgettable) ...@@ -3176,8 +3185,11 @@ push_overloaded_decl (decl, forgettable)
{ {
if (decl == tmp || duplicate_decls (decl, tmp)) if (decl == tmp || duplicate_decls (decl, tmp))
return tmp; return tmp;
if (compparms (TYPE_ARG_TYPES (TREE_TYPE (decl)), /* Avoid doing things about built-ins, since duplicate_decls
TYPE_ARG_TYPES (TREE_TYPE (tmp)), 2)) 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 ("new declaration `%#D'", decl);
cp_error_at ("ambiguates old declaration `%#D'", tmp); cp_error_at ("ambiguates old declaration `%#D'", tmp);
...@@ -3762,7 +3774,8 @@ lookup_nested_type (type, context) ...@@ -3762,7 +3774,8 @@ lookup_nested_type (type, context)
} }
break; break;
case FUNCTION_DECL: 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; break;
default: default:
my_friendly_abort (12); my_friendly_abort (12);
...@@ -3778,6 +3791,7 @@ lookup_nested_type (type, context) ...@@ -3778,6 +3791,7 @@ lookup_nested_type (type, context)
definitions if there are many, or return 0 if it is undefined. 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 > 0, we prefer TYPE_DECLs.
If PREFER_TYPE is -2, we're being called from yylex(). (UGLY)
Otherwise we prefer non-TYPE_DECLs. */ Otherwise we prefer non-TYPE_DECLs. */
tree tree
...@@ -3786,7 +3800,43 @@ lookup_name (name, prefer_type) ...@@ -3786,7 +3800,43 @@ lookup_name (name, prefer_type)
int prefer_type; int prefer_type;
{ {
register tree val; 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 if (current_binding_level != global_binding_level
&& IDENTIFIER_LOCAL_VALUE (name)) && IDENTIFIER_LOCAL_VALUE (name))
val = IDENTIFIER_LOCAL_VALUE (name); val = IDENTIFIER_LOCAL_VALUE (name);
...@@ -3802,7 +3852,7 @@ lookup_name (name, prefer_type) ...@@ -3802,7 +3852,7 @@ lookup_name (name, prefer_type)
/* Try to find values from base classes /* Try to find values from base classes
if we are presently defining a type. if we are presently defining a type.
We are presently only interested in TYPE_DECLs. */ 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) if (val == error_mark_node)
return val; return val;
if (val && TREE_CODE (val) != TYPE_DECL) if (val && TREE_CODE (val) != TYPE_DECL)
...@@ -3813,7 +3863,7 @@ lookup_name (name, prefer_type) ...@@ -3813,7 +3863,7 @@ lookup_name (name, prefer_type)
the nested name at the point where we haven't even, for example, the nested name at the point where we haven't even, for example,
created the COMPONENT_REF or anything like that. */ created the COMPONENT_REF or anything like that. */
if (val == NULL_TREE) if (val == NULL_TREE)
val = lookup_nested_field (name, prefer_type != -2); val = lookup_nested_field (name, ! yylex);
if (val == NULL_TREE) if (val == NULL_TREE)
val = IDENTIFIER_GLOBAL_VALUE (name); val = IDENTIFIER_GLOBAL_VALUE (name);
...@@ -3821,21 +3871,19 @@ lookup_name (name, prefer_type) ...@@ -3821,21 +3871,19 @@ lookup_name (name, prefer_type)
else else
val = IDENTIFIER_GLOBAL_VALUE (name); val = IDENTIFIER_GLOBAL_VALUE (name);
done:
if (val) if (val)
{ {
extern int looking_for_typename;
/* Arbitrate between finding a TYPE_DECL and finding /* Arbitrate between finding a TYPE_DECL and finding
other kinds of _DECLs. */ 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; return val;
if (IDENTIFIER_HAS_TYPE_VALUE (name)) if (IDENTIFIER_HAS_TYPE_VALUE (name))
{ {
register tree val_as_type = TYPE_NAME (IDENTIFIER_TYPE_VALUE (name)); register tree val_as_type = TYPE_NAME (IDENTIFIER_TYPE_VALUE (name));
if (val == val_as_type || prefer_type > 0 if (val == val_as_type || prefer_type > 0)
|| looking_for_typename > 0)
return val_as_type; return val_as_type;
return val; return val;
...@@ -4088,7 +4136,8 @@ init_decl_processing () ...@@ -4088,7 +4136,8 @@ init_decl_processing ()
error_mark_list = build_tree_list (error_mark_node, error_mark_node); error_mark_list = build_tree_list (error_mark_node, error_mark_node);
TREE_TYPE (error_mark_list) = 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; global_binding_level = current_binding_level;
this_identifier = get_identifier (THIS_NAME); this_identifier = get_identifier (THIS_NAME);
...@@ -4229,7 +4278,8 @@ init_decl_processing () ...@@ -4229,7 +4278,8 @@ init_decl_processing ()
TREE_TYPE (void_zero_node) = void_type_node; TREE_TYPE (void_zero_node) = void_type_node;
string_type_node = build_pointer_type (char_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); record_builtin_type (RID_MAX, NULL_PTR, string_type_node);
/* Make a type to be the domain of a few array types /* Make a type to be the domain of a few array types
...@@ -4257,7 +4307,8 @@ init_decl_processing () ...@@ -4257,7 +4307,8 @@ init_decl_processing ()
build_pointer_type (default_function_type); build_pointer_type (default_function_type);
ptr_type_node = build_pointer_type (void_type_node); 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); record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node);
endlink = void_list_node; endlink = void_list_node;
int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink); int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink);
...@@ -4269,14 +4320,16 @@ init_decl_processing () ...@@ -4269,14 +4320,16 @@ init_decl_processing ()
double_ftype_double_double double_ftype_double_double
= build_function_type (double_type_node, = 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 int_ftype_int
= build_function_type (integer_type_node, int_endlink); = build_function_type (integer_type_node, int_endlink);
long_ftype_long long_ftype_long
= build_function_type (long_integer_type_node, = 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 void_ftype_ptr_ptr_int
= build_function_type (void_type_node, = build_function_type (void_type_node,
...@@ -4466,7 +4519,8 @@ init_decl_processing () ...@@ -4466,7 +4519,8 @@ init_decl_processing ()
builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP, builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP,
NULL_PTR); NULL_PTR);
builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, 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 #if 0
/* Not yet. */ /* Not yet. */
builtin_function ("strncpy", strncpy_ftype, BUILT_IN_STRNCPY, NULL_PTR); builtin_function ("strncpy", strncpy_ftype, BUILT_IN_STRNCPY, NULL_PTR);
...@@ -4481,13 +4535,19 @@ init_decl_processing () ...@@ -4481,13 +4535,19 @@ init_decl_processing ()
or build_function_call. */ or build_function_call. */
builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, 0); builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, 0);
builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, 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_fceil", double_ftype_double, BUILT_IN_FCEIL, 0);
builtin_function ("__builtin_fmod", double_ftype_double_double, BUILT_IN_FMOD, 0); builtin_function ("__builtin_fmod", double_ftype_double_double,
builtin_function ("__builtin_frem", double_ftype_double_double, BUILT_IN_FREM, 0); BUILT_IN_FMOD, 0);
builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, BUILT_IN_MEMSET, 0); builtin_function ("__builtin_frem", double_ftype_double_double,
builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP, 0); BUILT_IN_FREM, 0);
builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN, 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 #endif
/* C++ extensions */ /* C++ extensions */
...@@ -4507,7 +4567,7 @@ init_decl_processing () ...@@ -4507,7 +4567,7 @@ init_decl_processing ()
TYPE_MODE (unknown_type_node) = TYPE_MODE (void_type_node); TYPE_MODE (unknown_type_node) = TYPE_MODE (void_type_node);
/* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */ /* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */
TREE_TYPE (unknown_type_node) = 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_POINTER_TO (unknown_type_node) = unknown_type_node;
TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node; TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
...@@ -4544,9 +4604,12 @@ init_decl_processing () ...@@ -4544,9 +4604,12 @@ init_decl_processing ()
fields names so that the debugger can use them. */ fields names so that the debugger can use them. */
memptr_type = make_lang_type (RECORD_TYPE); memptr_type = make_lang_type (RECORD_TYPE);
fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, delta_type_node); fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier, delta_type_node); delta_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, pfn_identifier, ptr_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, finish_builtin_type (memptr_type, VTBL_PTR_TYPE, fields, 2,
double_type_node); double_type_node);
...@@ -4588,9 +4651,15 @@ init_decl_processing () ...@@ -4588,9 +4651,15 @@ init_decl_processing ()
if (flag_handle_signatures) if (flag_handle_signatures)
{ {
sigtable_entry_type = make_lang_type (RECORD_TYPE); 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[0] = build_lang_field_decl (FIELD_DECL,
fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier (SIGTABLE_OFFSET_NAME), short_integer_type_node); get_identifier (SIGTABLE_CODE_NAME),
fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier (SIGTABLE_PFN_NAME), ptr_type_node); 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, finish_builtin_type (sigtable_entry_type, SIGTABLE_PTR_TYPE, fields, 2,
double_type_node); double_type_node);
sigtable_entry_type = build_type_variant (sigtable_entry_type, 1, 0); sigtable_entry_type = build_type_variant (sigtable_entry_type, 1, 0);
...@@ -4620,9 +4689,12 @@ init_decl_processing () ...@@ -4620,9 +4689,12 @@ init_decl_processing ()
__t_desc_type_node = make_lang_type (RECORD_TYPE); __t_desc_type_node = make_lang_type (RECORD_TYPE);
__i_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); __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); __t_desc_array_type =
__i_desc_array_type = build_array_type (TYPE_POINTER_TO (__i_desc_type_node), NULL_TREE); build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE);
__m_desc_array_type = build_array_type (TYPE_POINTER_TO (__m_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"), fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
string_type_node); string_type_node);
...@@ -4630,7 +4702,8 @@ init_decl_processing () ...@@ -4630,7 +4702,8 @@ init_decl_processing ()
unsigned_type_node); unsigned_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("bits"), fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("bits"),
unsigned_type_node); 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)); TYPE_POINTER_TO (__t_desc_type_node));
fields[4] = build_lang_field_decl (FIELD_DECL, fields[4] = build_lang_field_decl (FIELD_DECL,
get_identifier ("ivars_count"), get_identifier ("ivars_count"),
...@@ -4666,7 +4739,8 @@ init_decl_processing () ...@@ -4666,7 +4739,8 @@ init_decl_processing ()
integer_type_node); integer_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"), fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"),
TYPE_POINTER_TO (__t_desc_type_node)); 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: /* method descriptors look like this:
...@@ -4699,7 +4773,8 @@ init_decl_processing () ...@@ -4699,7 +4773,8 @@ init_decl_processing ()
short_integer_type_node); short_integer_type_node);
fields[7] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_types"), 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))); 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++. */ /* Now, C++. */
...@@ -4720,11 +4795,21 @@ init_decl_processing () ...@@ -4720,11 +4795,21 @@ init_decl_processing ()
tree_cons (NULL_TREE, sizetype, tree_cons (NULL_TREE, sizetype,
void_list_node)), void_list_node)),
NOT_BUILT_IN); 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], auto_function (ansi_opname[(int) DELETE_EXPR],
build_function_type (void_type_node, build_function_type (void_type_node,
tree_cons (NULL_TREE, ptr_type_node, tree_cons (NULL_TREE, ptr_type_node,
void_list_node)), void_list_node)),
NOT_BUILT_IN); 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 abort_fndecl
= define_function ("abort", = define_function ("abort",
...@@ -4889,7 +4974,8 @@ shadow_tag (declspecs) ...@@ -4889,7 +4974,8 @@ shadow_tag (declspecs)
function members. */ function members. */
if (TYPE_FIELDS (t)) 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); finish_anon_union (decl);
} }
else else
...@@ -4982,7 +5068,8 @@ start_decl (declarator, declspecs, initialized, raises) ...@@ -4982,7 +5068,8 @@ start_decl (declarator, declspecs, initialized, raises)
/* This should only be done once on the top most decl. */ /* This should only be done once on the top most decl. */
if (have_extern_spec && !used_extern_spec) 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; used_extern_spec = 1;
} }
...@@ -5057,9 +5144,11 @@ start_decl (declarator, declspecs, initialized, raises) ...@@ -5057,9 +5144,11 @@ start_decl (declarator, declspecs, initialized, raises)
DECL_ARGUMENTS (decl) = args; DECL_ARGUMENTS (decl) = args;
} }
d = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), TREE_TYPE (decl)); 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 (); 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); TREE_STATIC (d) = TREE_STATIC (decl);
DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl) DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl)
&& !(context && !DECL_THIS_EXTERN (decl))); && !(context && !DECL_THIS_EXTERN (decl)));
...@@ -5251,7 +5340,8 @@ start_decl (declarator, declspecs, initialized, raises) ...@@ -5251,7 +5340,8 @@ start_decl (declarator, declspecs, initialized, raises)
use temporary storage. Do this even if we will ignore the value. */ use temporary storage. Do this even if we will ignore the value. */
if (current_binding_level == global_binding_level && debug_temp_inits) 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 /* In this case, the initializer must lay down in permanent
storage, since it will be saved until `finish_file' is run. */ storage, since it will be saved until `finish_file' is run. */
; ;
...@@ -5463,7 +5553,8 @@ grok_reference_init (decl, type, init, cleanupp) ...@@ -5463,7 +5553,8 @@ grok_reference_init (decl, type, init, cleanupp)
TREE_OPERAND (TREE_OPERAND (tmp, 0), 2) = error_mark_node; TREE_OPERAND (TREE_OPERAND (tmp, 0), 2) = error_mark_node;
} }
if (IS_AGGR_TYPE (TREE_TYPE (this_ptr_type))) 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 else
DECL_INITIAL (decl) = convert (this_ptr_type, tmp); DECL_INITIAL (decl) = convert (this_ptr_type, tmp);
...@@ -5481,7 +5572,8 @@ grok_reference_init (decl, type, init, cleanupp) ...@@ -5481,7 +5572,8 @@ grok_reference_init (decl, type, init, cleanupp)
if (TREE_CODE (actual_init) == ADDR_EXPR if (TREE_CODE (actual_init) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (actual_init, 0)) == TARGET_EXPR) && TREE_CODE (TREE_OPERAND (actual_init, 0)) == TARGET_EXPR)
actual_init = save_expr (actual_init); 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)); DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
TREE_TYPE (DECL_INITIAL (decl)) = type; TREE_TYPE (DECL_INITIAL (decl)) = type;
} }
...@@ -5689,7 +5781,8 @@ finish_decl (decl, init, asmspec_tree, need_pop) ...@@ -5689,7 +5781,8 @@ finish_decl (decl, init, asmspec_tree, need_pop)
{ {
if (TYPE_NEEDS_CONSTRUCTING (type)) 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; init = error_mark_node;
} }
else else
...@@ -5780,7 +5873,8 @@ finish_decl (decl, init, asmspec_tree, need_pop) ...@@ -5780,7 +5873,8 @@ finish_decl (decl, init, asmspec_tree, need_pop)
if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (ctype)) if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (ctype))
cp_error ("structure `%D' with uninitialized const members", decl); cp_error ("structure `%D' with uninitialized const members", decl);
if (CLASSTYPE_REF_FIELDS_NEED_INIT (ctype)) 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 if (TREE_CODE (decl) == VAR_DECL
...@@ -6002,9 +6096,6 @@ finish_decl (decl, init, asmspec_tree, need_pop) ...@@ -6002,9 +6096,6 @@ finish_decl (decl, init, asmspec_tree, need_pop)
} }
else if (toplev) 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 this is a static const, change its apparent linkage
if it belongs to a #pragma interface. */ if it belongs to a #pragma interface. */
if (TREE_STATIC (decl) && !interface_unknown) if (TREE_STATIC (decl) && !interface_unknown)
...@@ -6092,7 +6183,8 @@ finish_decl (decl, init, asmspec_tree, need_pop) ...@@ -6092,7 +6183,8 @@ finish_decl (decl, init, asmspec_tree, need_pop)
: & TYPE_ARG_TYPES (type); : & TYPE_ARG_TYPES (type);
*argp = NULL_TREE; *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; *argp = parmtypes;
fndecl = build_decl (FUNCTION_DECL, fnname, type); fndecl = build_decl (FUNCTION_DECL, fnname, type);
DECL_EXTERNAL (fndecl) = DECL_EXTERNAL (decl); DECL_EXTERNAL (fndecl) = DECL_EXTERNAL (decl);
...@@ -6169,7 +6261,8 @@ finish_decl (decl, init, asmspec_tree, need_pop) ...@@ -6169,7 +6261,8 @@ finish_decl (decl, init, asmspec_tree, need_pop)
if (init || TYPE_NEEDS_CONSTRUCTING (type)) 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); expand_aggr_init (decl, init, 0);
} }
...@@ -6182,7 +6275,8 @@ finish_decl (decl, init, asmspec_tree, need_pop) ...@@ -6182,7 +6275,8 @@ finish_decl (decl, init, asmspec_tree, need_pop)
if (cleanup) if (cleanup)
{ {
if (! expand_decl_cleanup (decl, 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) ...@@ -6380,7 +6474,8 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
if (inlinep) if (inlinep)
cp_error ("`%D' declared as an `inline' %s", object, type); cp_error ("`%D' declared as an `inline' %s", object, type);
if (quals) 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) if (friendp)
cp_error_at ("invalid friend declaration", object); cp_error_at ("invalid friend declaration", object);
if (raises) if (raises)
...@@ -6399,7 +6494,8 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, 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 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. */ not look, and -1 if we should not call `grokclassfn' at all. */
static tree 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 ctype, type;
tree declarator; tree declarator;
int virtualp; int virtualp;
...@@ -6530,7 +6626,8 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, check, publ ...@@ -6530,7 +6626,8 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, check, publ
for (i = 0; i < n_baselinks; i++) for (i = 0; i < n_baselinks; i++)
{ {
tree base_binfo = TREE_VEC_ELT (binfos, 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, tmp = get_first_matching_virtual (base_binfo, decl,
flags == DTOR_FLAG); flags == DTOR_FLAG);
...@@ -6547,8 +6644,10 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, check, publ ...@@ -6547,8 +6644,10 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, check, publ
path to its virtual baseclass. */ path to its virtual baseclass. */
if (staticp) if (staticp)
{ {
cp_error ("method `%D' may not be declared static", decl); cp_error ("method `%D' may not be declared static",
cp_error_at ("(since `%D' declared virtual in base class.)", tmp); decl);
cp_error_at ("(since `%D' declared virtual in base class.)",
tmp);
break; break;
} }
virtualp = 1; virtualp = 1;
...@@ -6716,7 +6815,8 @@ build_ptrmemfunc_type (type) ...@@ -6716,7 +6815,8 @@ build_ptrmemfunc_type (type)
u = make_lang_type (UNION_TYPE); u = make_lang_type (UNION_TYPE);
fields[0] = build_lang_field_decl (FIELD_DECL, pfn_identifier, 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); finish_builtin_type (u, "__ptrmemfunc_type", fields, 1, ptr_type_node);
TYPE_NAME (u) = NULL_TREE; TYPE_NAME (u) = NULL_TREE;
...@@ -6725,8 +6825,10 @@ build_ptrmemfunc_type (type) ...@@ -6725,8 +6825,10 @@ build_ptrmemfunc_type (type)
/* Let the front-end know this is a pointer to member function. */ /* Let the front-end know this is a pointer to member function. */
TYPE_PTRMEMFUNC_FLAG(t) = 1; TYPE_PTRMEMFUNC_FLAG(t) = 1;
fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, delta_type_node); fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier, delta_type_node); 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); fields[2] = build_lang_field_decl (FIELD_DECL, pfn_or_delta2_identifier, u);
finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node); finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node);
...@@ -6839,7 +6941,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -6839,7 +6941,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
tree ctype = current_class_type; tree ctype = current_class_type;
tree ctor_return_type = NULL_TREE; tree ctor_return_type = NULL_TREE;
enum overload_flags flags = NO_SPECIAL; enum overload_flags flags = NO_SPECIAL;
int seen_scope_ref = 0;
tree quals = NULL_TREE; tree quals = NULL_TREE;
RIDBIT_RESET_ALL (specbits); RIDBIT_RESET_ALL (specbits);
...@@ -6957,7 +7058,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -6957,7 +7058,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
dname = decl; dname = decl;
decl = NULL_TREE; 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); my_friendly_assert (flags == NO_SPECIAL, 154);
flags = TYPENAME_FLAG; flags = TYPENAME_FLAG;
...@@ -6987,11 +7089,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -6987,11 +7089,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
/* C++ extension */ /* C++ extension */
case SCOPE_REF: 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. /* Perform error checking, and convert class names to types.
We may call grokdeclarator multiple times for the same We may call grokdeclarator multiple times for the same
...@@ -7239,14 +7336,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -7239,14 +7336,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
} }
else else
{ {
if (funcdef_flag && warn_return_type if (funcdef_flag)
&& return_type == return_normal {
&& ! (RIDBIT_SETP (RID_SIGNED, specbits) if (warn_return_type
|| RIDBIT_SETP (RID_UNSIGNED, specbits) && return_type == return_normal
|| RIDBIT_SETP (RID_LONG, specbits) && ! (RIDBIT_SETP (RID_SIGNED, specbits)
|| RIDBIT_SETP (RID_SHORT, specbits))) || RIDBIT_SETP (RID_UNSIGNED, specbits)
warn_about_return_type = 1; || RIDBIT_SETP (RID_LONG, specbits)
/* Save warning until we know what is really going on. */ || 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; type = integer_type_node;
} }
} }
...@@ -7486,7 +7593,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -7486,7 +7593,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
} }
if (volatilep) if (volatilep)
{ {
error ("`volatile' specified for signature member function `%s'", name); error ("`volatile' specified for signature member function `%s'",
name);
volatilep = 0; volatilep = 0;
} }
if (inlinep) if (inlinep)
...@@ -7502,7 +7610,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -7502,7 +7610,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
} }
if (virtualp) 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. */ /* Later, we'll make signature member functions virtual. */
virtualp = 0; virtualp = 0;
} }
...@@ -7816,7 +7925,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -7816,7 +7925,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
else else
{ {
if (pedantic) 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: dont_grok_size:
itype = itype =
build_binary_op (MINUS_EXPR, size, integer_one_node, 1); build_binary_op (MINUS_EXPR, size, integer_one_node, 1);
...@@ -8177,11 +8287,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -8177,11 +8287,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
/* don't fall out into global scope. Hides real bug? --eichin */ ; /* don't fall out into global scope. Hides real bug? --eichin */ ;
else if (TREE_COMPLEXITY (declarator) == current_class_depth) else if (TREE_COMPLEXITY (declarator) == current_class_depth)
{ {
/* I'm not really sure what pushclass calls this popclass /* This pop_nested_class corresponds to the
corresponds to. One is in build_push_scope and that has push_nested_class used to push into class scope for
been changed to a push_nested_class call, that's why I parsing the argument list of a function decl, in
try to use pop_nested_class here instead. qualified_id. */
-niklas@appli.se */
pop_nested_class (1); pop_nested_class (1);
TREE_COMPLEXITY (declarator) = current_class_depth; TREE_COMPLEXITY (declarator) = current_class_depth;
} }
...@@ -8631,7 +8740,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -8631,7 +8740,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
} }
if (declarator == ansi_opname[(int) NEW_EXPR] 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) if (virtualp)
{ {
...@@ -9328,7 +9439,8 @@ grok_ctor_properties (ctype, decl) ...@@ -9328,7 +9439,8 @@ grok_ctor_properties (ctype, decl)
} }
/* An operator with this name can be either unary or binary. */ /* An operator with this name can be either unary or binary. */
int ambi_op_p (name) static int
ambi_op_p (name)
tree name; tree name;
{ {
return (name == ansi_opname [(int) INDIRECT_REF] return (name == ansi_opname [(int) INDIRECT_REF]
...@@ -9340,7 +9452,8 @@ int ambi_op_p (name) ...@@ -9340,7 +9452,8 @@ int ambi_op_p (name)
} }
/* An operator with this name can only be unary. */ /* An operator with this name can only be unary. */
int unary_op_p (name) static int
unary_op_p (name)
tree name; tree name;
{ {
return (name == ansi_opname [(int) TRUTH_NOT_EXPR] return (name == ansi_opname [(int) TRUTH_NOT_EXPR]
...@@ -9358,44 +9471,39 @@ grok_op_properties (decl, virtualp, friendp) ...@@ -9358,44 +9471,39 @@ grok_op_properties (decl, virtualp, friendp)
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE); int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
tree name = DECL_NAME (decl); tree name = DECL_NAME (decl);
tree t;
if (! friendp) if (current_class_type == NULL_TREE)
for (t = current_class_type; t; t = TYPE_NEXT_VARIANT (t)) friendp = 1;
{
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 (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 /* 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. */ doesn't look at the class declaration to find out if it's static. */
my_friendly_assert (!methodp, 355); if (methodp)
#endif revert_static_member_fn (&TREE_TYPE (decl), &decl,
&TYPE_ARG_TYPES (TREE_TYPE (decl)));
/* Take care of function decl if we had syntax errors. */ /* Take care of function decl if we had syntax errors. */
if (argtypes == NULL_TREE) if (argtypes == NULL_TREE)
...@@ -9404,18 +9512,14 @@ grok_op_properties (decl, virtualp, friendp) ...@@ -9404,18 +9512,14 @@ grok_op_properties (decl, virtualp, friendp)
hash_tree_chain (integer_type_node, hash_tree_chain (integer_type_node,
void_list_node)); void_list_node));
else 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) DELETE_EXPR]
else if (name == ansi_opname[(int) VEC_NEW_EXPR]) || name == ansi_opname[(int) VEC_DELETE_EXPR])
{
}
#endif
else if (name == ansi_opname[(int) DELETE_EXPR])
{ {
#if 0 if (methodp)
my_friendly_assert (!methodp, 355); revert_static_member_fn (&TREE_TYPE (decl), &decl,
#endif &TYPE_ARG_TYPES (TREE_TYPE (decl)));
if (argtypes == NULL_TREE) if (argtypes == NULL_TREE)
TREE_TYPE (decl) = TREE_TYPE (decl) =
...@@ -9423,13 +9527,15 @@ grok_op_properties (decl, virtualp, friendp) ...@@ -9423,13 +9527,15 @@ grok_op_properties (decl, virtualp, friendp)
hash_tree_chain (ptr_type_node, hash_tree_chain (ptr_type_node,
void_list_node)); void_list_node));
else else
decl = coerce_delete_type (TREE_TYPE (decl)); {
} TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
#if 0
else if (name == ansi_opname[(int) VEC_DELETE_EXPR]) 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 else
{ {
/* An operator function must either be a non-static member function /* An operator function must either be a non-static member function
...@@ -9484,8 +9590,9 @@ grok_op_properties (decl, virtualp, friendp) ...@@ -9484,8 +9590,9 @@ grok_op_properties (decl, virtualp, friendp)
parmtype = TREE_VALUE (TREE_CHAIN (argtypes)); parmtype = TREE_VALUE (TREE_CHAIN (argtypes));
if (TREE_CODE (parmtype) == REFERENCE_TYPE if (TREE_CODE (parmtype) == REFERENCE_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) && (TYPE_MAIN_VARIANT (TREE_TYPE (parmtype))
== current_class_type) == current_class_type)
&& ! friendp)
{ {
TYPE_HAS_ASSIGN_REF (current_class_type) = 1; TYPE_HAS_ASSIGN_REF (current_class_type) = 1;
if (TYPE_READONLY (TREE_TYPE (parmtype))) if (TYPE_READONLY (TREE_TYPE (parmtype)))
...@@ -9957,9 +10064,8 @@ if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE ...@@ -9957,9 +10064,8 @@ if (CLASSTYPE_N_BASECLASSES (basetype) == NULL_TREE
} }
TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype); TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype);
TREE_GETS_NEW (ref) |= TREE_GETS_NEW (basetype); TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
TREE_GETS_PLACED_NEW (ref) |= TREE_GETS_PLACED_NEW (basetype); TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
TREE_GETS_DELETE (ref) |= TREE_GETS_DELETE (basetype);
CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype); CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
i += 1; i += 1;
} }
...@@ -10439,7 +10545,8 @@ start_function (declspecs, declarator, raises, pre_parsed_p) ...@@ -10439,7 +10545,8 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
/* If this doesn't return integer_type, complain. */ /* If this doesn't return integer_type, complain. */
if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node) 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; TREE_TYPE (decl1) = fntype = default_function_type;
} }
warn_about_return_type = 0; warn_about_return_type = 0;
...@@ -11040,7 +11147,7 @@ finish_function (lineno, call_poplevel) ...@@ -11040,7 +11147,7 @@ finish_function (lineno, call_poplevel)
/* These are two cases where we cannot delegate deletion. */ /* These are two cases where we cannot delegate deletion. */
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type) 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, exprstmt = build_delete (current_class_type, C_C_D, integer_zero_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
else else
...@@ -11096,7 +11203,7 @@ finish_function (lineno, call_poplevel) ...@@ -11096,7 +11203,7 @@ finish_function (lineno, call_poplevel)
virtual_size = c_sizeof (current_class_type); virtual_size = c_sizeof (current_class_type);
/* At the end, call delete if that's what's requested. */ /* 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. */ /* This NOP_EXPR means we are in a static call context. */
exprstmt = exprstmt =
build_method_call build_method_call
...@@ -11216,7 +11323,7 @@ finish_function (lineno, call_poplevel) ...@@ -11216,7 +11323,7 @@ finish_function (lineno, call_poplevel)
expand_decl_init (allocated_this); expand_decl_init (allocated_this);
/* How we cleanup `this' if an exception was raised before /* How we cleanup `this' if an exception was raised before
we are ready to bail out. */ 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) ? build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, allocated_this, virtual_size, NULL_TREE)
/* The size of allocated_this is wrong, and hence the /* The size of allocated_this is wrong, and hence the
second argument to operator delete will be wrong. */ second argument to operator delete will be wrong. */
......
...@@ -1071,6 +1071,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete) ...@@ -1071,6 +1071,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
return error_mark_node; return error_mark_node;
} }
#if 0
/* If the type has no destructor, then we should build a regular /* If the type has no destructor, then we should build a regular
delete, instead of a vector delete. Otherwise, we would end delete, instead of a vector delete. Otherwise, we would end
up passing a bogus offset into __builtin_delete, which is up passing a bogus offset into __builtin_delete, which is
...@@ -1082,15 +1083,15 @@ delete_sanity (exp, size, doing_vec, use_global_delete) ...@@ -1082,15 +1083,15 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
doing_vec = 0; doing_vec = 0;
use_global_delete = 1; use_global_delete = 1;
} }
#endif
if (doing_vec) if (doing_vec)
return build_vec_delete (t, maxindex, elt_size, NULL_TREE, return build_vec_delete (t, maxindex, elt_size, integer_one_node,
integer_one_node, integer_two_node); integer_two_node, use_global_delete);
else else
return build_delete (type, t, integer_three_node, return build_delete (type, t, integer_three_node,
LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE, LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE,
use_global_delete use_global_delete);
|| TYPE_HAS_DESTRUCTOR (TREE_TYPE (type)));
} }
/* Sanity check: report error if this function FUNCTION is not /* Sanity check: report error if this function FUNCTION is not
...@@ -1456,6 +1457,7 @@ grokbitfield (declarator, declspecs, width) ...@@ -1456,6 +1457,7 @@ grokbitfield (declarator, declspecs, width)
return value; return value;
} }
#if 0
/* Like GROKFIELD, except that the declarator has been /* Like GROKFIELD, except that the declarator has been
buried in DECLSPECS. Find the declarator, and buried in DECLSPECS. Find the declarator, and
return something that looks like it came from return something that looks like it came from
...@@ -1634,6 +1636,7 @@ groktypefield (declspecs, parmlist) ...@@ -1634,6 +1636,7 @@ groktypefield (declspecs, parmlist)
DECL_IN_AGGR_P (decl) = 1; DECL_IN_AGGR_P (decl) = 1;
return decl; return decl;
} }
#endif
tree tree
grokoptypename (declspecs, declarator) grokoptypename (declspecs, declarator)
...@@ -2278,7 +2281,7 @@ coerce_delete_type (type) ...@@ -2278,7 +2281,7 @@ coerce_delete_type (type)
else if (e3 |= e2) else if (e3 |= e2)
{ {
if (arg_types == NULL_TREE) if (arg_types == NULL_TREE)
arg_types = void_list_node; arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
else else
arg_types = tree_cons (NULL_TREE, ptr_type_node, TREE_CHAIN (arg_types)); arg_types = tree_cons (NULL_TREE, ptr_type_node, TREE_CHAIN (arg_types));
} }
...@@ -2853,7 +2856,11 @@ reparse_decl_as_expr1 (decl) ...@@ -2853,7 +2856,11 @@ reparse_decl_as_expr1 (decl)
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
return build_x_unary_op (BIT_NOT_EXPR, return build_x_unary_op (BIT_NOT_EXPR,
reparse_decl_as_expr1 (TREE_OPERAND (decl, 0))); 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: default:
my_friendly_abort (5); my_friendly_abort (5);
return NULL_TREE; return NULL_TREE;
...@@ -2901,6 +2908,9 @@ finish_decl_parsing (decl) ...@@ -2901,6 +2908,9 @@ finish_decl_parsing (decl)
push_nested_class (TREE_OPERAND (decl, 0), 3); push_nested_class (TREE_OPERAND (decl, 0), 3);
TREE_COMPLEXITY (decl) = current_class_depth; TREE_COMPLEXITY (decl) = current_class_depth;
return decl; return decl;
case ARRAY_REF:
TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0));
return decl;
default: default:
my_friendly_abort (5); my_friendly_abort (5);
return NULL_TREE; return NULL_TREE;
......
...@@ -1059,17 +1059,18 @@ It is ambiguous whether @code{class T} should be parsed as the ...@@ -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 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 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 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 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 @code{sizeof}. Section 8.1 of the pre-San Diego working paper specifies
that these ambiguous constructs will be interpreted as @code{typename}s. 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 3) Between @code{functional_cast} and
@code{expr_or_declarator}/@code{complex_direct_notype_declarator}, for @code{complex_direct_notype_declarator}, for various token strings.
various token strings. This situation occurs in code looking like This situation occurs in code looking like
@example @example
int (*a); int (*a);
...@@ -1078,11 +1079,23 @@ int (*a); ...@@ -1078,11 +1079,23 @@ int (*a);
This code is ambiguous; it could be a declaration of the variable 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} 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 @samp{*a} to @samp{int}. Section 6.8 specifies that the former
interpretation is correct. This ambiguity results in 12 reduce/reduce interpretation is correct. This ambiguity results in 7 reduce/reduce
conflicts. Ack. conflicts. Another aspect of this ambiguity is code like 'int (x[2]);',
which is resolved at the '[' and accounts for 6 reduce/reduce conflicts
4) Between @code{after_type_declarator} and @code{parm}, for the token between @samp{direct_notype_declarator} and
@code{TYPENAME}. This occurs in (as one example) code like @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 @example
typedef int foo, bar; typedef int foo, bar;
...@@ -1093,11 +1106,12 @@ class A @{ ...@@ -1093,11 +1106,12 @@ class A @{
What is @code{bar} inside the class definition? We currently interpret 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 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 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 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 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. Unlike the others, this ambiguity is not recognized by the Working Paper.
......
...@@ -52,12 +52,11 @@ static void expand_recursive_init_1 (); ...@@ -52,12 +52,11 @@ static void expand_recursive_init_1 ();
static void expand_recursive_init (); static void expand_recursive_init ();
static void expand_virtual_init PROTO((tree, tree, tree)); static void expand_virtual_init PROTO((tree, tree, tree));
tree expand_vec_init (); tree expand_vec_init ();
tree build_vec_delete ();
static void add_friend (), add_friends (); static void add_friend (), add_friends ();
/* Cache _builtin_new and _builtin_delete exprs. */ /* 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. */ /* Cache the identifier nodes for the two magic field of a new cookie. */
static tree nc_nelts_field_id; static tree nc_nelts_field_id;
...@@ -81,6 +80,10 @@ void init_init_processing () ...@@ -81,6 +80,10 @@ void init_init_processing ()
TREE_USED (TREE_OPERAND (BIN, 0)) = 0; TREE_USED (TREE_OPERAND (BIN, 0)) = 0;
BID = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) DELETE_EXPR]))); BID = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) DELETE_EXPR])));
TREE_USED (TREE_OPERAND (BID, 0)) = 0; 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); minus_one = build_int_2 (-1, -1);
/* Define the structure that holds header information for /* Define the structure that holds header information for
...@@ -1801,12 +1804,10 @@ is_aggr_typedef (name, or_else) ...@@ -1801,12 +1804,10 @@ is_aggr_typedef (name, or_else)
if (IDENTIFIER_HAS_TYPE_VALUE (name)) if (IDENTIFIER_HAS_TYPE_VALUE (name))
type = IDENTIFIER_TYPE_VALUE (name); type = IDENTIFIER_TYPE_VALUE (name);
else if (IDENTIFIER_HAS_CLASS_TYPE_VALUE (name))
type = IDENTIFIER_CLASS_TYPE_VALUE (name);
else else
{ {
if (or_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; return 0;
} }
...@@ -1814,7 +1815,7 @@ is_aggr_typedef (name, or_else) ...@@ -1814,7 +1815,7 @@ is_aggr_typedef (name, or_else)
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM) && TREE_CODE (type) != TEMPLATE_TYPE_PARM)
{ {
if (or_else) 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 0;
} }
return 1; return 1;
...@@ -1833,8 +1834,6 @@ get_aggr_from_typedef (name, or_else) ...@@ -1833,8 +1834,6 @@ get_aggr_from_typedef (name, or_else)
if (IDENTIFIER_HAS_TYPE_VALUE (name)) if (IDENTIFIER_HAS_TYPE_VALUE (name))
type = IDENTIFIER_TYPE_VALUE (name); type = IDENTIFIER_TYPE_VALUE (name);
else if (IDENTIFIER_HAS_CLASS_TYPE_VALUE (name))
type = IDENTIFIER_CLASS_TYPE_VALUE (name);
else else
{ {
if (or_else) if (or_else)
...@@ -1861,8 +1860,6 @@ get_type_value (name) ...@@ -1861,8 +1860,6 @@ get_type_value (name)
if (IDENTIFIER_HAS_TYPE_VALUE (name)) if (IDENTIFIER_HAS_TYPE_VALUE (name))
return IDENTIFIER_TYPE_VALUE (name); return IDENTIFIER_TYPE_VALUE (name);
else if (IDENTIFIER_CLASS_VALUE (name))
return IDENTIFIER_CLASS_TYPE_VALUE (name);
else else
return NULL_TREE; return NULL_TREE;
} }
...@@ -2808,13 +2805,6 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals) ...@@ -2808,13 +2805,6 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals)
TREE_PUBLIC (decl) = 1; TREE_PUBLIC (decl) = 1;
add_friend (current_class_type, decl); add_friend (current_class_type, decl);
DECL_FRIEND_P (decl) = 1; 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; decl = void_type_node;
} }
/* A global friend. /* A global friend.
...@@ -2980,6 +2970,7 @@ build_new (placement, decl, init, use_global_new) ...@@ -2980,6 +2970,7 @@ build_new (placement, decl, init, use_global_new)
tree type, true_type, size, rval; tree type, true_type, size, rval;
tree nelts; tree nelts;
int has_array = 0; int has_array = 0;
enum tree_code code = NEW_EXPR;
tree pending_sizes = NULL_TREE; tree pending_sizes = NULL_TREE;
...@@ -3155,27 +3146,28 @@ build_new (placement, decl, init, use_global_new) ...@@ -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 /* Get a little extra space to store a couple of things before the new'ed
array. */ array. */
if (has_array && TYPE_NEEDS_DESTRUCTOR (true_type)) if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type))
{ {
tree extra = BI_header_size; tree extra = BI_header_size;
size = size_binop (PLUS_EXPR, size, extra); size = size_binop (PLUS_EXPR, size, extra);
} }
if (has_array)
code = VEC_NEW_EXPR;
/* Allocate the object. */ /* Allocate the object. */
if (TYPE_LANG_SPECIFIC (true_type) if (! use_global_new && TYPE_LANG_SPECIFIC (true_type)
&& (TREE_GETS_NEW (true_type) || TREE_GETS_PLACED_NEW (true_type)) && (TYPE_GETS_NEW (true_type) & (1 << has_array)))
&& !use_global_new rval = build_opfncall (code, LOOKUP_NORMAL,
&& !has_array)
rval = build_opfncall (NEW_EXPR, LOOKUP_NORMAL,
TYPE_POINTER_TO (true_type), size, placement); TYPE_POINTER_TO (true_type), size, placement);
else if (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); ptr_type_node, size, placement);
rval = convert (TYPE_POINTER_TO (true_type), rval); 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) && TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node)
{ {
if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST) if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)
...@@ -3189,7 +3181,8 @@ build_new (placement, decl, init, use_global_new) ...@@ -3189,7 +3181,8 @@ build_new (placement, decl, init, use_global_new)
else else
{ {
rval = build_builtin_call (build_pointer_type (true_type), 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 #if 0
/* See comment above as to why this is disabled. */ /* See comment above as to why this is disabled. */
if (alignment) if (alignment)
...@@ -3202,14 +3195,13 @@ build_new (placement, decl, init, use_global_new) ...@@ -3202,14 +3195,13 @@ build_new (placement, decl, init, use_global_new)
} }
#endif #endif
TREE_CALLS_NEW (rval) = 1; 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 /* 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 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) */ cookies? And how does that interact with the code below? (mrs) */
/* Finish up some magic for new'ed arrays */ /* 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 extra = BI_header_size;
tree cookie, exp1; tree cookie, exp1;
...@@ -3594,20 +3586,21 @@ expand_vec_init (decl, base, maxindex, init, from_array) ...@@ -3594,20 +3586,21 @@ expand_vec_init (decl, base, maxindex, init, from_array)
This does not call any destructors. */ This does not call any destructors. */
tree tree
build_x_delete (type, addr, use_global_delete, virtual_size) build_x_delete (type, addr, which_delete, virtual_size)
tree type, addr; tree type, addr;
int use_global_delete; int which_delete;
tree virtual_size; tree virtual_size;
{ {
int use_global_delete = which_delete & 1;
int use_vec_delete = !!(which_delete & 2);
tree rval; tree rval;
enum tree_code code = use_vec_delete ? VEC_DELETE_EXPR : DELETE_EXPR;
if (!use_global_delete if (! use_global_delete && TYPE_LANG_SPECIFIC (TREE_TYPE (type))
&& TYPE_LANG_SPECIFIC (TREE_TYPE (type)) && (TYPE_GETS_DELETE (TREE_TYPE (type)) & (1 << use_vec_delete)))
&& TREE_GETS_DELETE (TREE_TYPE (type))) rval = build_opfncall (code, LOOKUP_NORMAL, addr, virtual_size, NULL_TREE);
rval = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr,
virtual_size, NULL_TREE);
else 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)); build_tree_list (NULL_TREE, addr));
return rval; return rval;
} }
...@@ -3674,7 +3667,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) ...@@ -3674,7 +3667,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
addr = save_expr (addr); addr = save_expr (addr);
return build_vec_delete (addr, array_type_nelts (type), return build_vec_delete (addr, array_type_nelts (type),
c_sizeof_nowarn (TREE_TYPE (type)), c_sizeof_nowarn (TREE_TYPE (type)),
NULL_TREE, auto_delete, integer_two_node); auto_delete, integer_two_node,
use_global_delete);
} }
else else
{ {
...@@ -3707,10 +3701,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) ...@@ -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 /* Pass the size of the object down to the operator delete() in
addition to the ADDR. */ 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); tree virtual_size = c_sizeof_nowarn (type);
return build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr, return build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr,
virtual_size, NULL_TREE); virtual_size, NULL_TREE);
...@@ -3837,7 +3829,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) ...@@ -3837,7 +3829,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
operator delete, call the parent parent destructor (if any), operator delete, call the parent parent destructor (if any),
but let this node do the deleting. Otherwise, it is ok but let this node do the deleting. Otherwise, it is ok
to let the parent destructor do the deleting. */ 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; parent_auto_delete = integer_zero_node;
if (auto_delete == integer_zero_node) if (auto_delete == integer_zero_node)
...@@ -3970,8 +3962,6 @@ build_vbase_delete (type, decl) ...@@ -3970,8 +3962,6 @@ build_vbase_delete (type, decl)
MAXINDEX is the number of elements to be deleted. MAXINDEX is the number of elements to be deleted.
ELT_SIZE is the nominal size of each element in the vector. ELT_SIZE is the nominal size of each element in the vector.
BASE is the expression that should yield the store to be deleted. 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. This function expands (or synthesizes) these calls itself.
AUTO_DELETE_VEC says whether the container (vector) should be deallocated. AUTO_DELETE_VEC says whether the container (vector) should be deallocated.
AUTO_DELETE say whether each item in the container should be deallocated. AUTO_DELETE say whether each item in the container should be deallocated.
...@@ -3985,10 +3975,11 @@ build_vbase_delete (type, decl) ...@@ -3985,10 +3975,11 @@ build_vbase_delete (type, decl)
confirm the size, and trap if the numbers differ; not clear that it'd confirm the size, and trap if the numbers differ; not clear that it'd
be worth bothering.) */ be worth bothering.) */
tree 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 base, maxindex, elt_size;
tree dtor_dummy;
tree auto_delete_vec, auto_delete; tree auto_delete_vec, auto_delete;
int use_global_delete;
{ {
tree ptype = TREE_TYPE (base); tree ptype = TREE_TYPE (base);
tree type; tree type;
...@@ -4081,7 +4072,8 @@ build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_de ...@@ -4081,7 +4072,8 @@ build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_de
/* This is the real size */ /* This is the real size */
virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size); virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
body = build_tree_list (NULL_TREE, 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)); virtual_size));
body = build (COND_EXPR, void_type_node, body = build (COND_EXPR, void_type_node,
build (BIT_AND_EXPR, integer_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 ...@@ -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 */ /* The below is short by BI_header_size */
virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex)); virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex));
if (loop == integer_zero_node) if (! TYPE_VEC_NEW_USES_COOKIE (type))
/* no header */ /* no header */
base_tbd = base; base_tbd = base;
else else
...@@ -4137,7 +4129,8 @@ build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_de ...@@ -4137,7 +4129,8 @@ build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_de
/* True size with header. */ /* True size with header. */
virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size); 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); virtual_size);
if (auto_delete_vec != integer_one_node) if (auto_delete_vec != integer_one_node)
deallocate_expr = build (COND_EXPR, void_type_node, deallocate_expr = build (COND_EXPR, void_type_node,
......
...@@ -542,6 +542,10 @@ init_lex () ...@@ -542,6 +542,10 @@ init_lex ()
IDENTIFIER_OPNAME_P (ansi_opname[(int) NEW_EXPR]) = 1; IDENTIFIER_OPNAME_P (ansi_opname[(int) NEW_EXPR]) = 1;
ansi_opname[(int) DELETE_EXPR] = get_identifier ("__dl"); ansi_opname[(int) DELETE_EXPR] = get_identifier ("__dl");
IDENTIFIER_OPNAME_P (ansi_opname[(int) DELETE_EXPR]) = 1; 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"); ansi_opname[(int) TYPE_EXPR] = get_identifier ("__op");
IDENTIFIER_OPNAME_P (ansi_opname[(int) TYPE_EXPR]) = 1; IDENTIFIER_OPNAME_P (ansi_opname[(int) TYPE_EXPR]) = 1;
...@@ -681,6 +685,8 @@ init_lex () ...@@ -681,6 +685,8 @@ init_lex ()
opname_tab[(int) MODIFY_EXPR] = "="; opname_tab[(int) MODIFY_EXPR] = "=";
opname_tab[(int) NEW_EXPR] = "new"; opname_tab[(int) NEW_EXPR] = "new";
opname_tab[(int) DELETE_EXPR] = "delete"; 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) COND_EXPR] = "... ? ... : ...";
opname_tab[(int) CALL_EXPR] = "()"; opname_tab[(int) CALL_EXPR] = "()";
opname_tab[(int) PLUS_EXPR] = "+"; opname_tab[(int) PLUS_EXPR] = "+";
...@@ -841,10 +847,7 @@ yyprint (file, yychar, yylval) ...@@ -841,10 +847,7 @@ yyprint (file, yychar, yylval)
case IDENTIFIER_DEFN: case IDENTIFIER_DEFN:
case TYPENAME_DEFN: case TYPENAME_DEFN:
case PTYPENAME_DEFN: case PTYPENAME_DEFN:
case TYPENAME_COLON:
case TYPENAME_ELLIPSIS: case TYPENAME_ELLIPSIS:
case SCOPED_TYPENAME:
case SCOPED_NAME:
case SCSPEC: case SCSPEC:
case PRE_PARSED_CLASS_DECL: case PRE_PARSED_CLASS_DECL:
t = yylval.ttype; t = yylval.ttype;
...@@ -2324,14 +2327,15 @@ check_newline () ...@@ -2324,14 +2327,15 @@ check_newline ()
register int c; register int c;
register int token; register int token;
lineno++; /* Read first nonwhite char on the line. Do this before incrementing the
line number, in case we're at the end of saved text. */
/* Read first nonwhite char on the line. */
do do
c = getch (); c = getch ();
while (c == ' ' || c == '\t'); while (c == ' ' || c == '\t');
lineno++;
if (c != '#') if (c != '#')
{ {
/* If not #, return it so caller will use it. */ /* If not #, return it so caller will use it. */
...@@ -3080,12 +3084,13 @@ readescape (ignore_ptr) ...@@ -3080,12 +3084,13 @@ readescape (ignore_ptr)
return c; return c;
} }
/* Value is 1 if we should try to make the next identifier look like a /* Value is 1 (or 2) if we should try to make the next identifier look like
typename (when it may be a local variable or a class variable). 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 0 if we treat this name in a default fashion. */
Value is -1 if we must not see a type name. */
int looking_for_typename = 0; int looking_for_typename = 0;
#if 0
/* NO LONGER USED: Value is -1 if we must not see a type name. */
void void
dont_see_typename () dont_see_typename ()
{ {
...@@ -3096,6 +3101,7 @@ dont_see_typename () ...@@ -3096,6 +3101,7 @@ dont_see_typename ()
lastiddecl = 0; lastiddecl = 0;
} }
} }
#endif
#ifdef __GNUC__ #ifdef __GNUC__
extern __inline int identifier_type (); extern __inline int identifier_type ();
...@@ -3119,7 +3125,7 @@ see_typename () ...@@ -3119,7 +3125,7 @@ see_typename ()
looking_for_typename = 0; looking_for_typename = 0;
if (yychar == IDENTIFIER) if (yychar == IDENTIFIER)
{ {
lastiddecl = lookup_name (yylval.ttype, -1); lastiddecl = lookup_name (yylval.ttype, -2);
if (lastiddecl == 0) if (lastiddecl == 0)
{ {
if (flag_labels_ok) if (flag_labels_ok)
...@@ -3540,7 +3546,6 @@ real_yylex () ...@@ -3540,7 +3546,6 @@ real_yylex ()
} }
if (value == NEW && ! global_bindings_p ()) if (value == NEW && ! global_bindings_p ())
{ {
looking_for_typename = 1;
value = NEW; value = NEW;
goto done; goto done;
} }
......
...@@ -114,6 +114,9 @@ extern char *token_buffer; /* Pointer to token buffer. */ ...@@ -114,6 +114,9 @@ extern char *token_buffer; /* Pointer to token buffer. */
/* Back-door communication channel to the lexer. */ /* Back-door communication channel to the lexer. */
extern int looking_for_typename; extern int looking_for_typename;
/* Tell the lexer where to look for names. */
extern tree got_scope;
/* Pending language change. /* Pending language change.
Positive is push count, negative is pop count. */ Positive is push count, negative is pop count. */
extern int pending_lang_change; extern int pending_lang_change;
......
...@@ -840,27 +840,22 @@ build_decl_overload (dname, parms, for_method) ...@@ -840,27 +840,22 @@ build_decl_overload (dname, parms, for_method)
{ {
char *name = IDENTIFIER_POINTER (dname); char *name = IDENTIFIER_POINTER (dname);
if (dname == ansi_opname[(int) NEW_EXPR] /* member operators new and delete look like methods at this point. */
&& parms != NULL_TREE if (! for_method && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST)
&& TREE_CODE (parms) == TREE_LIST {
&& TREE_VALUE (parms) == sizetype if (TREE_VALUE (parms) == sizetype
&& TREE_CHAIN (parms) == void_list_node) && TREE_CHAIN (parms) == void_list_node)
return get_identifier ("__builtin_new"); {
else if (dname == ansi_opname[(int) DELETE_EXPR] if (dname == ansi_opname[(int) NEW_EXPR])
&& parms != NULL_TREE return get_identifier ("__builtin_new");
&& TREE_CODE (parms) == TREE_LIST else if (dname == ansi_opname[(int) VEC_NEW_EXPR])
&& TREE_VALUE (parms) == ptr_type_node return get_identifier ("__builtin_vec_new");
&& TREE_CHAIN (parms) == void_list_node) }
return get_identifier ("__builtin_delete"); else if (dname == ansi_opname[(int) DELETE_EXPR])
else if (dname == ansi_opname[(int) DELETE_EXPR] return get_identifier ("__builtin_delete");
&& parms != NULL_TREE else if (dname == ansi_opname[(int) VEC_DELETE_EXPR])
&& TREE_CODE (parms) == TREE_LIST return get_identifier ("__builtin_vec_delete");
&& 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");
OB_INIT (); OB_INIT ();
if (for_method != 2) if (for_method != 2)
...@@ -1112,19 +1107,19 @@ build_opfncall (code, flags, xarg1, xarg2, arg3) ...@@ -1112,19 +1107,19 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
try_second = 0; try_second = 0;
break; break;
case VEC_NEW_EXPR:
case 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) if (flags & LOOKUP_GLOBAL)
return build_overload_call (fnname, tree_cons (NULL_TREE, xarg2, arg3), return build_overload_call (fnname, args, flags & LOOKUP_COMPLAIN,
flags & LOOKUP_COMPLAIN,
(struct candidate *)0); (struct candidate *)0);
rval = build_method_call rval = build_method_call
(build_indirect_ref (build1 (NOP_EXPR, xarg1, error_mark_node), (build_indirect_ref (build1 (NOP_EXPR, xarg1, error_mark_node),
"new"), "new"),
fnname, tree_cons (NULL_TREE, xarg2, arg3), fnname, args, NULL_TREE, flags);
NULL_TREE, flags);
if (rval == error_mark_node) if (rval == error_mark_node)
/* User might declare fancy operator new, but invoke it /* User might declare fancy operator new, but invoke it
like standard one. */ like standard one. */
...@@ -1136,13 +1131,13 @@ build_opfncall (code, flags, xarg1, xarg2, arg3) ...@@ -1136,13 +1131,13 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
} }
break; break;
case VEC_DELETE_EXPR:
case DELETE_EXPR: case DELETE_EXPR:
{ {
fnname = ansi_opname[(int) DELETE_EXPR]; fnname = ansi_opname[(int) code];
if (flags & LOOKUP_GLOBAL) if (flags & LOOKUP_GLOBAL)
return build_overload_call (fnname, return build_overload_call (fnname,
tree_cons (NULL_TREE, xarg1, build_tree_list (NULL_TREE, xarg1),
build_tree_list (NULL_TREE, xarg2)),
flags & LOOKUP_COMPLAIN, flags & LOOKUP_COMPLAIN,
(struct candidate *)0); (struct candidate *)0);
...@@ -1151,7 +1146,7 @@ build_opfncall (code, flags, xarg1, xarg2, arg3) ...@@ -1151,7 +1146,7 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
error_mark_node), error_mark_node),
NULL_PTR), NULL_PTR),
fnname, tree_cons (NULL_TREE, xarg1, fnname, tree_cons (NULL_TREE, xarg1,
build_tree_list (NULL_TREE, xarg2)), build_tree_list (NULL_TREE, xarg2)),
NULL_TREE, flags); NULL_TREE, flags);
/* This happens when the user mis-declares `operator delete'. /* This happens when the user mis-declares `operator delete'.
Should now be impossible. */ Should now be impossible. */
......
...@@ -66,12 +66,16 @@ extern int errno; ...@@ -66,12 +66,16 @@ extern int errno;
#endif #endif
extern int end_of_file; extern int end_of_file;
extern int current_class_depth;
void yyerror (); void yyerror ();
/* Like YYERROR but do call yyerror. */ /* Like YYERROR but do call yyerror. */
#define YYERROR1 { yyerror ("syntax error"); 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 /* Contains the statement keyword (if/while/do) to include in an
error message if the user supplies an empty conditional expression. */ error message if the user supplies an empty conditional expression. */
static char *cond_stmt_keyword; static char *cond_stmt_keyword;
...@@ -112,12 +116,6 @@ empty_parms () ...@@ -112,12 +116,6 @@ empty_parms ()
but they can also serve as typespecs in declarations. */ but they can also serve as typespecs in declarations. */
%token TYPENAME %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. /* Reserved words that specify storage class.
yylval contains an IDENTIFIER_NODE which indicates which one. */ yylval contains an IDENTIFIER_NODE which indicates which one. */
%token SCSPEC %token SCSPEC
...@@ -156,11 +154,6 @@ empty_parms () ...@@ -156,11 +154,6 @@ empty_parms ()
%token TYPEID DYNAMIC_CAST %token TYPEID DYNAMIC_CAST
%token <itype> SCOPE %token <itype> 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. /* Define the operator tokens and their precedences.
The value is an integer because, if used, it is the tree code The value is an integer because, if used, it is the tree code
to use in the expression made from the operator. */ to use in the expression made from the operator. */
...@@ -173,7 +166,7 @@ empty_parms () ...@@ -173,7 +166,7 @@ empty_parms ()
%nonassoc IF %nonassoc IF
%nonassoc ELSE %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 '{' ',' ';' %left '{' ',' ';'
...@@ -217,30 +210,28 @@ empty_parms () ...@@ -217,30 +210,28 @@ empty_parms ()
%type <ttype> compstmt except_stmts ansi_except_stmts implicitly_scoped_stmt %type <ttype> compstmt except_stmts ansi_except_stmts implicitly_scoped_stmt
%type <ttype> declarator notype_declarator after_type_declarator %type <ttype> declarator notype_declarator after_type_declarator
%type <ttype> notype_declarator1 after_type_declarator1
%type <ttype> direct_notype_declarator direct_after_type_declarator %type <ttype> direct_notype_declarator direct_after_type_declarator
%type <ttype> structsp opt.component_decl_list component_decl_list %type <ttype> structsp opt.component_decl_list component_decl_list
%type <ttype> component_decl components component_declarator %type <ttype> component_decl components component_declarator
%type <ttype> notype_components notype_component_declarator %type <ttype> notype_components notype_component_declarator
%type <ttype> after_type_component_declarator after_type_component_declarator0 %type <ttype> after_type_component_declarator after_type_component_declarator0
%type <ttype> notype_component_declarator0 %type <ttype> notype_component_declarator0 component_decl_1
%type <ttype> enumlist enumerator %type <ttype> enumlist enumerator
%type <ttype> type_id absdcl absdcl1 type_quals %type <ttype> type_id absdcl type_quals
%type <ttype> direct_abstract_declarator conversion_declarator %type <ttype> direct_abstract_declarator conversion_declarator
%type <ttype> new_type_id new_declarator direct_new_declarator %type <ttype> new_type_id new_declarator direct_new_declarator
%type <ttype> xexpr parmlist parms parm bad_parm %type <ttype> xexpr parmlist parms parm bad_parm
%type <ttype> identifiers_or_typenames %type <ttype> identifiers_or_typenames
%type <ttype> fcast_or_absdcl regcast_or_absdcl sub_cast_expr %type <ttype> fcast_or_absdcl regcast_or_absdcl sub_cast_expr
%type <ttype> expr_or_declarator complex_notype_declarator1 %type <ttype> expr_or_declarator complex_notype_declarator
%type <ttype> notype_unqualified_id %type <ttype> notype_unqualified_id unqualified_id qualified_id
%type <ttype> overqualified_id notype_qualified_id
%type <ttype> complex_direct_notype_declarator functional_cast %type <ttype> complex_direct_notype_declarator functional_cast
%type <ttype> named_parm complex_parmlist typed_declspecs1 parms_comma %type <ttype> named_parm complex_parmlist typed_declspecs1 parms_comma
/* C++ extensions */ /* C++ extensions */
%type <ttype> typename_scope %token <ttype> TYPENAME_ELLIPSIS PTYPENAME
%token <ttype> TYPENAME_COLON TYPENAME_ELLIPSIS
%token <ttype> PTYPENAME SCOPED_TYPENAME SCOPED_NAME
%token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL %token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL
%token <ttype> PRE_PARSED_CLASS_DECL %token <ttype> PRE_PARSED_CLASS_DECL
%type <ttype> fn.def1 /* Not really! */ %type <ttype> fn.def1 /* Not really! */
...@@ -251,21 +242,26 @@ empty_parms () ...@@ -251,21 +242,26 @@ empty_parms ()
%type <itype> base_class_access_list %type <itype> base_class_access_list
%type <ttype> base_class maybe_base_class_list base_class.1 %type <ttype> base_class maybe_base_class_list base_class.1
%type <ttype> maybe_raises raise_identifier raise_identifiers ansi_raise_identifier ansi_raise_identifiers %type <ttype> maybe_raises raise_identifier raise_identifiers ansi_raise_identifier ansi_raise_identifiers
%type <ttype> component_declarator0 id_scope scoped_typename scoped_base_class %type <ttype> component_declarator0
%type <ttype> forhead.1 identifier_or_opname operator_name %type <ttype> forhead.1 operator_name
%type <ttype> new delete object aggr %type <ttype> new object aggr
%type <itype> delete
/* %type <ttype> primary_no_id */ /* %type <ttype> primary_no_id */
%type <ttype> nonmomentary_expr %type <ttype> nonmomentary_expr
%type <itype> forhead.2 initdcl0 notype_initdcl0 member_init_list %type <itype> forhead.2 initdcl0 notype_initdcl0 member_init_list
%type <itype> .scope try ansi_try %type <itype> .scope try ansi_try
%type <ttype> template_header template_parm_list template_parm %type <ttype> template_header template_parm_list template_parm
%type <ttype> template_type template_arg_list template_arg %type <ttype> template_type template_arg_list template_arg
%type <ttype> template_instantiation template_type_name tmpl.1 tmpl.2 %type <ttype> template_instantiation template_type_name tmpl.2
%type <ttype> template_instantiate_once template_instantiate_some %type <ttype> template_instantiate_once template_instantiate_some
%type <itype> fn_tmpl_end %type <itype> fn_tmpl_end
/* %type <itype> try_for_typename */ /* %type <itype> try_for_typename */
%type <ttype> condition partially_scoped_stmt xcond paren_cond_or_null %type <ttype> condition partially_scoped_stmt xcond paren_cond_or_null
%type <strtype> .kindof_pushlevel %type <strtype> .kindof_pushlevel
%type <ttype> type_name nested_name_specifier nested_type ptr_to_mem
%type <ttype> qualified_type_name complete_type_name notype_identifier
%type <ttype> complex_type_name nested_name_specifier_1
%type <itype> nomods_initdecls nomods_initdcl0
/* in order to recognize aggr tags as defining and thus shadowing. */ /* in order to recognize aggr tags as defining and thus shadowing. */
%token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN %token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN
...@@ -405,15 +401,6 @@ template_parm: ...@@ -405,15 +401,6 @@ template_parm:
warning ("restricted template type parameters not yet implemented"); warning ("restricted template type parameters not yet implemented");
$$ = build_tree_list ($2, $4); $$ = 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 | parm
; ;
...@@ -528,11 +515,8 @@ fn_tmpl_end: '{' { $$ = '{'; } ...@@ -528,11 +515,8 @@ fn_tmpl_end: '{' { $$ = '{'; }
; ;
datadef: datadef:
notype_initdecls ';' nomods_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"); }
| declmods notype_initdecls ';' | declmods notype_initdecls ';'
{} {}
/* Normal case to make fast: "const i;". */ /* Normal case to make fast: "const i;". */
...@@ -649,26 +633,6 @@ fn.def1: ...@@ -649,26 +633,6 @@ fn.def1:
YYERROR1; YYERROR1;
reinit_parse_for_function (); reinit_parse_for_function ();
$$ = NULL_TREE; } $$ = 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 | PRE_PARSED_FUNCTION_DECL
{ start_function (NULL_TREE, TREE_VALUE ($$), NULL_TREE, 1); { start_function (NULL_TREE, TREE_VALUE ($$), NULL_TREE, 1);
reinit_parse_for_function (); } reinit_parse_for_function (); }
...@@ -679,8 +643,9 @@ fn.def1: ...@@ -679,8 +643,9 @@ fn.def1:
fn.def2: fn.def2:
typed_declspecs '(' parmlist ')' type_quals maybe_raises typed_declspecs '(' parmlist ')' type_quals maybe_raises
{ {
tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), $3, $5); $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1), $3, $5);
$$ = start_method (TREE_CHAIN ($$), decl, $6); $$ = start_method (TREE_CHAIN ($1), $$, $6);
rest_of_mdef:
if (! $$) if (! $$)
YYERROR1; YYERROR1;
if (yychar == YYEMPTY) if (yychar == YYEMPTY)
...@@ -688,52 +653,17 @@ fn.def2: ...@@ -688,52 +653,17 @@ fn.def2:
reinit_parse_for_method (yychar, $$); } reinit_parse_for_method (yychar, $$); }
| typed_declspecs LEFT_RIGHT type_quals maybe_raises | typed_declspecs LEFT_RIGHT type_quals maybe_raises
{ {
tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), empty_parms (), $3); $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1),
$$ = start_method (TREE_CHAIN ($$), decl, $4); empty_parms (), $3);
if (! $$) $$ = start_method (TREE_CHAIN ($1), $$, $4);
YYERROR1; goto rest_of_mdef;
if (yychar == YYEMPTY) }
yychar = YYLEX;
reinit_parse_for_method (yychar, $$); }
| typed_declspecs declarator maybe_raises | typed_declspecs declarator maybe_raises
{ $$ = start_method ($$, $2, $3); { $$ = start_method ($$, $2, $3); goto rest_of_mdef; }
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, $$); }
| declmods notype_declarator maybe_raises | declmods notype_declarator maybe_raises
{ $$ = start_method ($$, $2, $3); { $$ = start_method ($$, $2, $3); goto rest_of_mdef; }
if (! $$)
YYERROR1;
if (yychar == YYEMPTY)
yychar = YYLEX;
reinit_parse_for_method (yychar, $$); }
| notype_declarator maybe_raises | notype_declarator maybe_raises
{ $$ = start_method (NULL_TREE, $$, $2); { $$ = start_method (NULL_TREE, $$, $2); goto rest_of_mdef; }
if (! $$)
YYERROR1;
if (yychar == YYEMPTY)
yychar = YYLEX;
reinit_parse_for_method (yychar, $$); }
; ;
return_id: RETURN IDENTIFIER return_id: RETURN IDENTIFIER
...@@ -811,27 +741,22 @@ member_init: '(' nonnull_exprlist ')' ...@@ -811,27 +741,22 @@ member_init: '(' nonnull_exprlist ')'
pedwarn ("anachronistic old style base class initializer"); pedwarn ("anachronistic old style base class initializer");
expand_member_init (C_C_D, NULL_TREE, void_type_node); expand_member_init (C_C_D, NULL_TREE, void_type_node);
} }
| identifier '(' nonnull_exprlist ')' | notype_identifier '(' nonnull_exprlist ')'
{
expand_member_init (C_C_D, $<ttype>$, $3);
}
| identifier LEFT_RIGHT
{ expand_member_init (C_C_D, $<ttype>$, void_type_node); }
| template_type_name '(' nonnull_exprlist ')'
{ expand_member_init (C_C_D, $<ttype>$, $3); } { expand_member_init (C_C_D, $<ttype>$, $3); }
| template_type_name LEFT_RIGHT | notype_identifier LEFT_RIGHT
{ expand_member_init (C_C_D, $<ttype>$, void_type_node); } { expand_member_init (C_C_D, $<ttype>$, void_type_node); }
| scoped_typename '(' nonnull_exprlist ')' | complete_type_name '(' nonnull_exprlist ')'
{ expand_member_init (C_C_D, $<ttype>$, $3); } { expand_member_init (C_C_D, $<ttype>$, $3); }
| scoped_typename LEFT_RIGHT | complete_type_name LEFT_RIGHT
{ expand_member_init (C_C_D, $<ttype>$, void_type_node); } { expand_member_init (C_C_D, $<ttype>$, void_type_node); }
| id_scope identifier '(' nonnull_exprlist ')' /* GNU extension */
| notype_qualified_id '(' nonnull_exprlist ')'
{ {
do_member_init ($<ttype>$, $2, $4); do_member_init (OP0 ($1), OP1 ($1), $3);
} }
| id_scope identifier LEFT_RIGHT | notype_qualified_id LEFT_RIGHT
{ {
do_member_init ($<ttype>$, $2, void_type_node); do_member_init (OP0 ($1), OP1 ($1), void_type_node);
} }
; ;
...@@ -841,23 +766,17 @@ identifier: ...@@ -841,23 +766,17 @@ identifier:
| PTYPENAME | PTYPENAME
; ;
notype_identifier:
IDENTIFIER
| PTYPENAME %prec EMPTY
;
identifier_defn: identifier_defn:
IDENTIFIER_DEFN IDENTIFIER_DEFN
| TYPENAME_DEFN | TYPENAME_DEFN
| PTYPENAME_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: explicit_instantiation:
TEMPLATE aggr template_type TEMPLATE aggr template_type
| TEMPLATE typed_declspecs declarator | TEMPLATE typed_declspecs declarator
...@@ -865,32 +784,8 @@ explicit_instantiation: ...@@ -865,32 +784,8 @@ explicit_instantiation:
; ;
template_type: template_type:
template_type_name tmpl.1 template_instantiation template_type_name tmpl.2 template_instantiation
{ { if ($3) $$ = $3; }
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: template_type_name:
...@@ -900,16 +795,7 @@ template_type_name: ...@@ -900,16 +795,7 @@ template_type_name:
{ $$ = lookup_template_class ($$, $3, NULL_TREE); } { $$ = lookup_template_class ($$, $3, NULL_TREE); }
; ;
tmpl.1: tmpl.2: %prec EMPTY
/* 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 ($<ttype>0, 1); }
;
tmpl.2:
/* Always do expansion if it hasn't been done already. */ /* Always do expansion if it hasn't been done already. */
{ $$ = instantiate_class_template ($<ttype>0, 1); } { $$ = instantiate_class_template ($<ttype>0, 1); }
; ;
...@@ -961,7 +847,7 @@ template_instantiate_once: ...@@ -961,7 +847,7 @@ template_instantiate_once:
} }
left_curly opt.component_decl_list '}' left_curly opt.component_decl_list '}'
{ {
$$ = finish_struct ($<ttype>3, $5, 0); tree t = finish_struct ($<ttype>3, $5, 0);
pop_obstacks (); pop_obstacks ();
end_template_instantiation ($1); end_template_instantiation ($1);
...@@ -971,7 +857,7 @@ template_instantiate_once: ...@@ -971,7 +857,7 @@ template_instantiate_once:
pop_tinst_level(); pop_tinst_level();
CLASSTYPE_GOT_SEMICOLON ($$) = 1; CLASSTYPE_GOT_SEMICOLON (t) = 1;
} }
; ;
...@@ -1229,20 +1115,15 @@ unary_expr: ...@@ -1229,20 +1115,15 @@ unary_expr:
| .scope new '(' nonnull_exprlist ')' '(' type_id ')' | .scope new '(' nonnull_exprlist ')' '(' type_id ')'
{ $$ = build_new ($4, groktypename ($7), NULL_TREE, { $$ = build_new ($4, groktypename ($7), NULL_TREE,
$$ != 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 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 '[' ']' cast_expr %prec UNARY
{ $$ = delete_sanity ($4, NULL_TREE, 1, $$ != NULL_TREE); { $$ = delete_sanity ($4, NULL_TREE, 1, $1);
if (yychar == YYEMPTY) if (yychar == YYEMPTY)
yychar = YYLEX; } yychar = YYLEX; }
| delete '[' expr ']' cast_expr %prec UNARY | delete '[' expr ']' cast_expr %prec UNARY
{ $$ = delete_sanity ($5, $3, 2, $$ != NULL_TREE); { $$ = delete_sanity ($5, $3, 2, $1);
if (yychar == YYEMPTY) if (yychar == YYEMPTY)
yychar = YYLEX; } yychar = YYLEX; }
; ;
...@@ -1368,33 +1249,33 @@ expr_no_commas: ...@@ -1368,33 +1249,33 @@ expr_no_commas:
; ;
notype_unqualified_id: notype_unqualified_id:
'~' see_typename TYPENAME '~' see_typename identifier
{ { $$ = build_parse_node (BIT_NOT_EXPR, $3); }
destructor_name:
$$ = build_parse_node (BIT_NOT_EXPR, $3);
}
| '~' see_typename IDENTIFIER
{ goto destructor_name; }
| '~' see_typename PTYPENAME
{ goto destructor_name; }
| operator_name | operator_name
| IDENTIFIER | IDENTIFIER
| PTYPENAME %prec EMPTY | PTYPENAME %prec EMPTY
; ;
unqualified_id:
notype_unqualified_id
| TYPENAME
;
expr_or_declarator: 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); } { $$ = build_parse_node (INDIRECT_REF, $2); }
| '&' expr_or_declarator %prec UNARY | '&' expr_or_declarator %prec UNARY
{ $$ = build_parse_node (ADDR_EXPR, $2); } { $$ = build_parse_node (ADDR_EXPR, $2); }
| notype_unqualified_id
{ see_typename (); }
; ;
direct_notype_declarator: direct_notype_declarator:
complex_direct_notype_declarator complex_direct_notype_declarator
| notype_unqualified_id | notype_unqualified_id
{ see_typename (); } | notype_qualified_id
{ push_nested_class (TREE_TYPE (OP0 ($$)), 3);
TREE_COMPLEXITY ($$) = current_class_depth; }
; ;
primary: primary:
...@@ -1474,10 +1355,6 @@ primary: ...@@ -1474,10 +1355,6 @@ primary:
} }
| primary '[' expr ']' | primary '[' expr ']'
{ $$ = grok_array_decl ($$, $3); } { $$ = 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 | primary PLUSPLUS
{ /* If we get an OFFSET_REF, turn it into what it really { /* If we get an OFFSET_REF, turn it into what it really
means (e.g., a COMPONENT_REF). This way if we've got, means (e.g., a COMPONENT_REF). This way if we've got,
...@@ -1569,7 +1446,7 @@ primary: ...@@ -1569,7 +1446,7 @@ primary:
| TYPEID '(' type_id ')' | TYPEID '(' type_id ')'
{ tree type = groktypename ($3); { tree type = groktypename ($3);
$$ = get_typeid (type); } $$ = get_typeid (type); }
| SCOPE IDENTIFIER | global_scope IDENTIFIER
{ {
do_scoped_id: do_scoped_id:
$$ = IDENTIFIER_GLOBAL_VALUE ($2); $$ = IDENTIFIER_GLOBAL_VALUE ($2);
...@@ -1608,19 +1485,24 @@ primary: ...@@ -1608,19 +1485,24 @@ primary:
} }
} }
| SCOPE operator_name | global_scope operator_name
{ {
got_scope = NULL_TREE;
if (TREE_CODE ($2) == IDENTIFIER_NODE) if (TREE_CODE ($2) == IDENTIFIER_NODE)
goto do_scoped_id; goto do_scoped_id;
$$ = $2; $$ = $2;
} }
| id_scope identifier_or_opname %prec HYPERUNARY | overqualified_id %prec HYPERUNARY
{ $$ = build_offset_ref ($$, $2); } { $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
| id_scope identifier_or_opname '(' nonnull_exprlist ')' | overqualified_id '(' nonnull_exprlist ')'
{ $$ = build_member_call ($$, $2, $4); } { $$ = build_member_call (OP0 ($$), OP1 ($$), $3); }
| id_scope identifier_or_opname LEFT_RIGHT | overqualified_id LEFT_RIGHT
{ $$ = build_member_call ($$, $2, NULL_TREE); } { $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); }
| object identifier_or_opname '(' nonnull_exprlist ')' | 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 #if 0
/* This is a future direction of this code, but because /* This is a future direction of this code, but because
...@@ -1635,7 +1517,7 @@ primary: ...@@ -1635,7 +1517,7 @@ primary:
(LOOKUP_NORMAL|LOOKUP_AGGR)); (LOOKUP_NORMAL|LOOKUP_AGGR));
#endif #endif
} }
| object identifier_or_opname LEFT_RIGHT | object unqualified_id LEFT_RIGHT
{ {
#if 0 #if 0
/* This is a future direction of this code, but because /* This is a future direction of this code, but because
...@@ -1650,27 +1532,27 @@ primary: ...@@ -1650,27 +1532,27 @@ primary:
(LOOKUP_NORMAL|LOOKUP_AGGR)); (LOOKUP_NORMAL|LOOKUP_AGGR));
#endif #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"); 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)); (LOOKUP_NORMAL|LOOKUP_AGGR));
} }
else 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"); 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)); (LOOKUP_NORMAL|LOOKUP_AGGR));
} }
else 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 */ /* p->int::~int() is valid -- 12.4 */
| object '~' TYPESPEC LEFT_RIGHT | object '~' TYPESPEC LEFT_RIGHT
...@@ -1741,17 +1623,14 @@ new: NEW ...@@ -1741,17 +1623,14 @@ new: NEW
.scope: .scope:
/* empty */ /* empty */
{ $$ = 0; } { $$ = 0; }
| SCOPE | global_scope
{ $$ = 1; } { got_scope = NULL_TREE; $$ = 1; }
; ;
delete: DELETE delete: DELETE
{ $$ = NULL_TREE; } { $$ = 0; }
| SCOPE delete | global_scope delete
{ if ($2) { got_scope = NULL_TREE; $$ = 1; }
error ("extra `::' before `delete' ignored");
$$ = error_mark_node;
}
; ;
/* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */ /* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */
...@@ -1782,18 +1661,16 @@ object: primary '.' ...@@ -1782,18 +1661,16 @@ object: primary '.'
; ;
decl: decl:
typed_declspecs initdecls ';' /* Normal case: make this fast. */
{ typespec declarator ';'
resume_momentary ($2); { tree d = get_decl_list ($1);
note_list_got_semicolon ($1); int yes = suspend_momentary ();
} d = start_decl ($2, d, 0, NULL_TREE);
| typespec initdecls ';' finish_decl (d, NULL_TREE, NULL_TREE, 0);
{ resume_momentary (yes);
resume_momentary ($2);
if (IS_AGGR_TYPE_CODE (TREE_CODE ($1))) if (IS_AGGR_TYPE_CODE (TREE_CODE ($1)))
note_got_semicolon ($1); note_got_semicolon ($1);
} }
/* Normal case: make this fast. */
| typed_declspecs declarator ';' | typed_declspecs declarator ';'
{ tree d = $1; { tree d = $1;
int yes = suspend_momentary (); int yes = suspend_momentary ();
...@@ -1802,29 +1679,23 @@ decl: ...@@ -1802,29 +1679,23 @@ decl:
resume_momentary (yes); resume_momentary (yes);
note_list_got_semicolon ($1); note_list_got_semicolon ($1);
} }
| typespec declarator ';' | typespec initdecls ';'
{ tree d = get_decl_list ($1); {
int yes = suspend_momentary (); resume_momentary ($2);
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))) if (IS_AGGR_TYPE_CODE (TREE_CODE ($1)))
note_got_semicolon ($1); note_got_semicolon ($1);
} }
| declmods notype_initdecls ';' | typed_declspecs initdecls ';'
{ resume_momentary ((int) $<itype>2); } {
/* Normal case: make this fast. */ resume_momentary ($2);
| declmods notype_declarator ';' note_list_got_semicolon ($1);
{ tree d;
int yes = suspend_momentary ();
d = start_decl ($<ttype>2, $<ttype>$, 0, NULL_TREE);
finish_decl (d, NULL_TREE, NULL_TREE, 0);
resume_momentary (yes);
} }
| declmods notype_initdecls ';'
{ resume_momentary ($2); }
| typed_declspecs ';' | typed_declspecs ';'
{ {
shadow_tag ($<ttype>$); shadow_tag ($1);
note_list_got_semicolon ($<ttype>$); note_list_got_semicolon ($1);
} }
| declmods ';' | declmods ';'
{ warning ("empty declaration"); } { warning ("empty declaration"); }
...@@ -1950,22 +1821,7 @@ reserved_typespecquals: ...@@ -1950,22 +1821,7 @@ reserved_typespecquals:
typespec: structsp typespec: structsp
| TYPESPEC %prec EMPTY | TYPESPEC %prec EMPTY
| TYPENAME %prec EMPTY | complete_type_name
| 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($$);
}
}
| TYPEOF '(' expr ')' | TYPEOF '(' expr ')'
{ $$ = TREE_TYPE ($3); { $$ = TREE_TYPE ($3);
if (pedantic) if (pedantic)
...@@ -2002,7 +1858,6 @@ typespec: structsp ...@@ -2002,7 +1858,6 @@ typespec: structsp
$$ = error_mark_node; $$ = error_mark_node;
} }
} }
| template_type %prec EMPTY
; ;
/* A typespec that is a reserved word, or a type qualifier. */ /* A typespec that is a reserved word, or a type qualifier. */
...@@ -2022,6 +1877,11 @@ notype_initdecls: ...@@ -2022,6 +1877,11 @@ notype_initdecls:
| notype_initdecls ',' initdcl | notype_initdecls ',' initdcl
; ;
nomods_initdecls:
nomods_initdcl0
| nomods_initdecls ',' initdcl
;
maybeasm: maybeasm:
/* empty */ /* empty */
{ $$ = NULL_TREE; } { $$ = NULL_TREE; }
...@@ -2098,6 +1958,25 @@ notype_initdcl0: ...@@ -2098,6 +1958,25 @@ notype_initdcl0:
finish_decl (d, NULL_TREE, $3, 0); } finish_decl (d, NULL_TREE, $3, 0); }
; ;
nomods_initdcl0:
notype_declarator maybe_raises maybeasm maybe_attribute '='
{ current_declspecs = NULL_TREE;
$<itype>5 = suspend_momentary ();
$<ttype>$ = start_decl ($1, current_declspecs, 1, $2);
cplus_decl_attributes ($<ttype>$, $4); }
init
/* Note how the declaration of the variable is in effect while its init is parsed! */
{ finish_decl ($<ttype>6, $7, $3, 0);
$$ = $<itype>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 /* the * rules are dummies to accept the Apollo extended syntax
so that the header files compile. */ so that the header files compile. */
maybe_attribute: maybe_attribute:
...@@ -2223,6 +2102,8 @@ structsp: ...@@ -2223,6 +2102,8 @@ structsp:
check_for_missing_semicolon ($$); } check_for_missing_semicolon ($$); }
| ENUM identifier | ENUM identifier
{ $$ = xref_tag (enum_type_node, $2, NULL_TREE, 0); } { $$ = 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 */ /* C++ extensions, merged with C to avoid shift/reduce conflicts */
| class_head left_curly opt.component_decl_list '}' | class_head left_curly opt.component_decl_list '}'
...@@ -2319,11 +2200,11 @@ aggr: AGGR ...@@ -2319,11 +2200,11 @@ aggr: AGGR
named_class_head_sans_basetype: named_class_head_sans_basetype:
aggr identifier aggr identifier
{ aggr1: current_aggr = $$; $$ = $2; }
| aggr template_type_name %prec EMPTY
{ current_aggr = $$; $$ = $2; } { current_aggr = $$; $$ = $2; }
| aggr TYPENAME_COLON | aggr complex_type_name
{ yyungetc (':', 1); goto aggr1; } { current_aggr = $$; $$ = $2; }
| aggr template_type %prec EMPTY
{ current_aggr = $$; $$ = $2; }
| aggr template_type_name '{' | aggr template_type_name '{'
{ yyungetc ('{', 1); { yyungetc ('{', 1);
aggr2: aggr2:
...@@ -2415,10 +2296,6 @@ base_class: ...@@ -2415,10 +2296,6 @@ base_class:
else else
$$ = build_tree_list ((tree)access_default, $$); $$ = build_tree_list ((tree)access_default, $$);
} }
| scoped_base_class
{
goto do_base_class1;
}
| base_class_access_list base_class.1 | base_class_access_list base_class.1
{ {
tree type; tree type;
...@@ -2448,36 +2325,10 @@ base_class: ...@@ -2448,36 +2325,10 @@ base_class:
else else
$$ = build_tree_list ((tree) $$, $2); $$ = 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: base_class.1:
template_type_name tmpl.2 template_instantiation complete_type_name
{
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
| SIGOF '(' expr ')' | SIGOF '(' expr ')'
{ {
if (current_aggr == signature_type_node) if (current_aggr == signature_type_node)
...@@ -2585,9 +2436,11 @@ left_curly: '{' ...@@ -2585,9 +2436,11 @@ left_curly: '{'
} }
pushclass ($<ttype>0, 0); pushclass ($<ttype>0, 0);
TYPE_BEING_DEFINED ($<ttype>0) = 1; TYPE_BEING_DEFINED ($<ttype>0) = 1;
#if 0
t = TYPE_IDENTIFIER ($<ttype>0); t = TYPE_IDENTIFIER ($<ttype>0);
if (t && IDENTIFIER_TEMPLATE (t)) if (t && IDENTIFIER_TEMPLATE (t))
overload_template_name (t, 1); overload_template_name (t, 1);
#endif
} }
; ;
...@@ -2642,81 +2495,58 @@ component_decl_list: ...@@ -2642,81 +2495,58 @@ component_decl_list:
; ;
component_decl: 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 speed; we need to call grok_x_components for enums, so the
speedup would be insignificant. */ speedup would be insignificant. */
typed_declspecs components ';' typed_declspecs components
{ {
$$ = grok_x_components ($$, $2); $$ = grok_x_components ($$, $2);
end_exception_decls (); end_exception_decls ();
} }
/* These rules introduce a reduce/reduce conflict; in | declmods notype_components
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 ';'
{ {
$$ = grok_x_components ($$, $2); $$ = grok_x_components ($$, $2);
end_exception_decls (); end_exception_decls ();
} }
/* Normal case: make this fast. */ | notype_declarator maybe_raises maybeasm maybe_attribute
| declmods notype_declarator ';' { $$ = grokfield ($$, NULL_TREE, $2, NULL_TREE, $3);
{ $$ = grokfield ($<ttype>2, $<ttype>$, cplus_decl_attributes ($$, $4); }
NULL_TREE, NULL_TREE, NULL_TREE); } | ':' expr_no_commas
| 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 ';'
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); } { $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
| ':' expr_no_commas '}'
{ error ("missing ';' before right brace");
yyungetc ('}', 0);
$$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
| error | error
{ $$ = NULL_TREE; } { $$ = NULL_TREE; }
/* C++: handle constructors, destructors and inline functions */ /* These rules introduce a reduce/reduce conflict; in
/* note that INLINE is like a TYPESPEC */ typedef int foo, bar;
| fn.def2 ':' /* base_init compstmt */ class A {
{ $$ = finish_method ($$); } foo (bar);
| fn.def2 '{' /* nodecls compstmt */ };
{ $$ = finish_method ($$); } should "A::foo" be declared as a function or "A::bar" as a data
| notype_declarator maybe_raises ';' member? In other words, is "bar" an after_type_declarator or a
{ $$ = grokfield ($$, NULL_TREE, $2, NULL_TREE, NULL_TREE); } parmlist? */
| notype_declarator maybe_raises '}' | typed_declspecs '(' parmlist ')' type_quals
{ error ("missing ';' before right brace"); { $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1),
yyungetc ('}', 0); $3, $5);
$$ = grokfield ($$, NULL_TREE, $2, NULL_TREE, NULL_TREE); } $$ = 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. */ /* The case of exactly one component is handled directly by component_decl. */
...@@ -2850,13 +2680,6 @@ new_type_id: ...@@ -2850,13 +2680,6 @@ new_type_id:
{ $$ = build_decl_list ($$, NULL_TREE); } { $$ = build_decl_list ($$, NULL_TREE); }
; ;
/* ANSI abstract-declarator (8.1) */
absdcl:
absdcl1 %prec EMPTY
| START_DECLARATOR absdcl1 %prec EMPTY
{ $$ = $2; }
;
type_quals: type_quals:
/* empty */ %prec EMPTY /* empty */ %prec EMPTY
{ $$ = NULL_TREE; } { $$ = NULL_TREE; }
...@@ -2883,32 +2706,31 @@ nonmomentary_expr: ...@@ -2883,32 +2706,31 @@ nonmomentary_expr:
/* A declarator that is allowed only after an explicit typespec. */ /* A declarator that is allowed only after an explicit typespec. */
/* may all be followed by prec '.' */ /* may all be followed by prec '.' */
after_type_declarator: after_type_declarator:
after_type_declarator1 '*' nonempty_type_quals after_type_declarator %prec UNARY
| START_DECLARATOR after_type_declarator1
{ $$ = $2; }
;
after_type_declarator1:
'*' nonempty_type_quals after_type_declarator1 %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); } { $$ = 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); } { $$ = make_reference_declarator ($2, $3); }
| '*' after_type_declarator1 %prec UNARY | '*' after_type_declarator %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); } { $$ = make_pointer_declarator (NULL_TREE, $2); }
| '&' after_type_declarator1 %prec UNARY | '&' after_type_declarator %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); } { $$ = make_reference_declarator (NULL_TREE, $2); }
| id_scope '*' type_quals after_type_declarator1 | ptr_to_mem type_quals after_type_declarator
{ tree arg = make_pointer_declarator ($3, $4); { tree arg = make_pointer_declarator ($2, $3);
if (TREE_CODE ($$) != SCOPE_REF) $$ = build_parse_node (SCOPE_REF, $1, arg);
$$ = build_push_scope ($$, arg);
else if (TREE_OPERAND ($$, 1) == NULL_TREE)
TREE_OPERAND ($$, 1) = arg;
else
$$ = build_parse_node (SCOPE_REF, $$, arg);
} }
| direct_after_type_declarator | 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:
direct_after_type_declarator '(' nonnull_exprlist ')' type_quals %prec '.' direct_after_type_declarator '(' nonnull_exprlist ')' type_quals %prec '.'
{ $$ = build_parse_node (CALL_EXPR, $$, $3, $5); } { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); }
...@@ -2922,58 +2744,46 @@ direct_after_type_declarator: ...@@ -2922,58 +2744,46 @@ direct_after_type_declarator:
{ $$ = build_parse_node (ARRAY_REF, $$, $3); } { $$ = build_parse_node (ARRAY_REF, $$, $3); }
| direct_after_type_declarator '[' ']' | direct_after_type_declarator '[' ']'
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); } { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
| '(' after_type_declarator1 ')' | '(' after_type_declarator ')'
{ $$ = $2; } { $$ = $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 /* A declarator allowed whether or not there has been
an explicit typespec. These cannot redeclare a typedef-name. */ an explicit typespec. These cannot redeclare a typedef-name. */
notype_declarator: notype_declarator:
notype_declarator1 '*' nonempty_type_quals notype_declarator %prec UNARY
| START_DECLARATOR notype_declarator1
{ $$ = $2; }
;
notype_declarator1:
'*' nonempty_type_quals notype_declarator1 %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); } { $$ = make_pointer_declarator ($2, $3); }
| '&' nonempty_type_quals notype_declarator1 %prec UNARY | '&' nonempty_type_quals notype_declarator %prec UNARY
{ $$ = make_reference_declarator ($2, $3); } { $$ = make_reference_declarator ($2, $3); }
| '*' notype_declarator1 %prec UNARY | '*' notype_declarator %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); } { $$ = make_pointer_declarator (NULL_TREE, $2); }
| '&' notype_declarator1 %prec UNARY | '&' notype_declarator %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); } { $$ = make_reference_declarator (NULL_TREE, $2); }
| id_scope '*' type_quals notype_declarator1 | ptr_to_mem type_quals notype_declarator
{ tree arg = make_pointer_declarator ($3, $4); { tree arg = make_pointer_declarator ($2, $3);
if (TREE_CODE ($$) != SCOPE_REF) $$ = build_parse_node (SCOPE_REF, $1, arg);
$$ = build_push_scope ($$, arg);
else if (TREE_OPERAND ($$, 1) == NULL_TREE)
TREE_OPERAND ($$, 1) = arg;
else
$$ = build_parse_node (SCOPE_REF, $$, arg);
} }
| direct_notype_declarator | direct_notype_declarator
; ;
complex_notype_declarator1: complex_notype_declarator:
'*' nonempty_type_quals notype_declarator1 %prec UNARY '*' nonempty_type_quals notype_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); } { $$ = make_pointer_declarator ($2, $3); }
| '&' nonempty_type_quals notype_declarator1 %prec UNARY | '&' nonempty_type_quals notype_declarator %prec UNARY
{ $$ = make_reference_declarator ($2, $3); } { $$ = make_reference_declarator ($2, $3); }
| '*' complex_notype_declarator1 %prec UNARY | '*' complex_notype_declarator %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); } { $$ = make_pointer_declarator (NULL_TREE, $2); }
| '&' complex_notype_declarator1 %prec UNARY | '&' complex_notype_declarator %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); } { $$ = make_reference_declarator (NULL_TREE, $2); }
| id_scope '*' type_quals notype_declarator1 | ptr_to_mem type_quals notype_declarator
{ tree arg = make_pointer_declarator ($3, $4); { tree arg = make_pointer_declarator ($2, $3);
if (TREE_CODE ($$) != SCOPE_REF) $$ = build_parse_node (SCOPE_REF, $1, arg);
$$ = build_push_scope ($$, arg);
else if (TREE_OPERAND ($$, 1) == NULL_TREE)
TREE_OPERAND ($$, 1) = arg;
else
$$ = build_parse_node (SCOPE_REF, $$, arg);
} }
| complex_direct_notype_declarator | complex_direct_notype_declarator
; ;
...@@ -2989,40 +2799,30 @@ complex_direct_notype_declarator: ...@@ -2989,40 +2799,30 @@ complex_direct_notype_declarator:
{ $$ = build_parse_node (CALL_EXPR, $$, NULL_TREE, NULL_TREE); } { $$ = build_parse_node (CALL_EXPR, $$, NULL_TREE, NULL_TREE); }
| '(' expr_or_declarator ')' | '(' expr_or_declarator ')'
{ $$ = finish_decl_parsing ($2); } { $$ = finish_decl_parsing ($2); }
| '(' complex_notype_declarator1 ')' | '(' complex_notype_declarator ')'
{ $$ = $2; } { $$ = $2; }
| direct_notype_declarator '[' nonmomentary_expr ']' | direct_notype_declarator '[' nonmomentary_expr ']'
{ $$ = build_parse_node (ARRAY_REF, $$, $3); } { $$ = build_parse_node (ARRAY_REF, $$, $3); }
| direct_notype_declarator '[' ']' | direct_notype_declarator '[' ']'
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); } { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
;
/* C++ extensions. */ qualified_id:
| id_scope see_typename notype_unqualified_id nested_name_specifier unqualified_id
{ see_typename (); { got_scope = NULL_TREE;
if (TREE_CODE ($$) != SCOPE_REF) $$ = build_parse_node (SCOPE_REF, $$, $2); }
$$ = 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;
t = TREE_TYPE(TREE_OPERAND($2, 0)); notype_qualified_id:
if (t != current_class_type && nested_name_specifier notype_unqualified_id
TREE_CODE(t) != TEMPLATE_TYPE_PARM) { got_scope = NULL_TREE;
{ $$ = build_parse_node (SCOPE_REF, $$, $2); }
push_nested_class(t, 3); ;
TREE_COMPLEXITY ($2) = current_class_depth;
} overqualified_id:
$$ = $2; notype_qualified_id
} | global_scope notype_qualified_id
{ $$ = $2; }
; ;
functional_cast: functional_cast:
...@@ -3034,61 +2834,60 @@ functional_cast: ...@@ -3034,61 +2834,60 @@ functional_cast:
{ $$ = reparse_absdcl_as_expr ($$, $2); } { $$ = reparse_absdcl_as_expr ($$, $2); }
; ;
id_scope: typename_scope type_name:
{ tree t; TYPENAME
do_id_scope: | template_type %prec EMPTY
;
t = resolve_scope_to_name (NULL_TREE, $$); nested_name_specifier:
if (t == NULL_TREE) nested_name_specifier_1
{ | nested_name_specifier nested_name_specifier_1
cp_error ("`%T' is not a valid scope", $$); { $$ = $2; }
$$ = error_mark_node; ;
}
else /* Why the @#$%^& do type_name and notype_identifier need to be expanded
$$ = t; 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 | IDENTIFIER SCOPE
{ goto do_id_scope; }
| template_type SCOPE /* try_for_typename %prec EMPTY */
{ {
if ($$ == error_mark_node) failed_scope:
/* leave it alone */; cp_error ("`%D' is not an aggregate typedef",
else lastiddecl ? lastiddecl : $$);
{ $$ = error_mark_node;
$$ = resolve_scope_to_name (NULL_TREE, TYPE_IDENTIFIER ($$));
if ($$ == NULL_TREE)
{
error ("undefined explicitly scoped type");
$$ = error_mark_node;
}
}
/* if ($3) popclass (1); */
} }
| PTYPENAME SCOPE
{ goto failed_scope; } */
; ;
typename_scope: complete_type_name:
TYPENAME SCOPE; qualified_type_name
| global_scope qualified_type_name
{ $$ = $2; }
;
scoped_typename: SCOPED_TYPENAME complex_type_name:
| template_type SCOPED_TYPENAME nested_type
{ | global_scope qualified_type_name
/* Kludge!!! See rule "template_type" and the code { $$ = $2; }
* dealing with "template_type_seen_before_scope" in ;
* yylex(). */
$$ = $2; ptr_to_mem:
} nested_name_specifier '*'
/* | template_type SCOPE try_for_typename TYPENAME { got_scope = NULL_TREE; }
{ | global_scope nested_name_specifier '*'
if ($$ == error_mark_node) { $$ = $2; got_scope = NULL_TREE; }
; ;
else
{ /* All uses of explicit global scope must go through this nonterminal so
$$ = build_parse_node (SCOPE_REF, that got_scope will be set before yylex is called to get the next token. */
TYPE_IDENTIFIER ($$), global_scope:
$4); SCOPE
} { got_scope = void_type_node; }
if ($3) popclass (1);
} */
; ;
/* ANSI new-declarator (5.3.4) */ /* ANSI new-declarator (5.3.4) */
...@@ -3101,23 +2900,13 @@ new_declarator: ...@@ -3101,23 +2900,13 @@ new_declarator:
{ $$ = make_reference_declarator ($2, $3); } { $$ = make_reference_declarator ($2, $3); }
| '&' type_quals %prec EMPTY | '&' type_quals %prec EMPTY
{ $$ = make_reference_declarator ($2, NULL_TREE); } { $$ = make_reference_declarator ($2, NULL_TREE); }
| id_scope '*' type_quals %prec EMPTY | ptr_to_mem type_quals %prec EMPTY
{ tree arg = make_pointer_declarator ($3, NULL_TREE); { tree arg = make_pointer_declarator ($2, NULL_TREE);
if (TREE_CODE ($$) != SCOPE_REF) $$ = build_parse_node (SCOPE_REF, $1, arg);
$$ = build_push_scope ($$, arg);
else if (TREE_OPERAND ($$, 1) == NULL_TREE)
TREE_OPERAND ($$, 1) = arg;
else
$$ = build_parse_node (SCOPE_REF, $$, arg);
} }
| id_scope '*' type_quals new_declarator | ptr_to_mem type_quals new_declarator
{ tree arg = make_pointer_declarator ($3, $4); { tree arg = make_pointer_declarator ($2, $3);
if (TREE_CODE ($$) != SCOPE_REF) $$ = build_parse_node (SCOPE_REF, $1, arg);
$$ = build_push_scope ($$, arg);
else if (TREE_OPERAND ($$, 1) == NULL_TREE)
TREE_OPERAND ($$, 1) = arg;
else
$$ = build_parse_node (SCOPE_REF, $$, arg);
} }
| direct_new_declarator %prec EMPTY | direct_new_declarator %prec EMPTY
; ;
...@@ -3131,48 +2920,36 @@ direct_new_declarator: ...@@ -3131,48 +2920,36 @@ direct_new_declarator:
; ;
/* ANSI abstract-declarator (8.1) */ /* ANSI abstract-declarator (8.1) */
absdcl1: absdcl:
'*' nonempty_type_quals absdcl1 '*' nonempty_type_quals absdcl
{ $$ = make_pointer_declarator ($2, $3); } { $$ = make_pointer_declarator ($2, $3); }
| '*' absdcl1 | '*' absdcl
{ $$ = make_pointer_declarator (NULL_TREE, $2); } { $$ = make_pointer_declarator (NULL_TREE, $2); }
| '*' type_quals %prec EMPTY | '*' type_quals %prec EMPTY
{ $$ = make_pointer_declarator ($2, NULL_TREE); } { $$ = make_pointer_declarator ($2, NULL_TREE); }
| '&' nonempty_type_quals absdcl1 | '&' nonempty_type_quals absdcl
{ $$ = make_reference_declarator ($2, $3); } { $$ = make_reference_declarator ($2, $3); }
| '&' absdcl1 | '&' absdcl
{ $$ = make_reference_declarator (NULL_TREE, $2); } { $$ = make_reference_declarator (NULL_TREE, $2); }
| '&' type_quals %prec EMPTY | '&' type_quals %prec EMPTY
{ $$ = make_reference_declarator ($2, NULL_TREE); } { $$ = make_reference_declarator ($2, NULL_TREE); }
| id_scope '*' type_quals %prec EMPTY | ptr_to_mem type_quals %prec EMPTY
{ tree arg = make_pointer_declarator ($3, NULL_TREE); { tree arg = make_pointer_declarator ($2, NULL_TREE);
if (TREE_CODE ($$) != SCOPE_REF) $$ = build_parse_node (SCOPE_REF, $1, arg);
$$ = build_push_scope ($$, arg);
else if (TREE_OPERAND ($$, 1) == NULL_TREE)
TREE_OPERAND ($$, 1) = arg;
else
$$ = build_parse_node (SCOPE_REF, $$, arg);
} }
| id_scope '*' type_quals absdcl1 | ptr_to_mem type_quals absdcl
{ tree arg = make_pointer_declarator ($3, $4); { tree arg = make_pointer_declarator ($2, $3);
if (TREE_CODE ($$) != SCOPE_REF) $$ = build_parse_node (SCOPE_REF, $1, arg);
$$ = build_push_scope ($$, arg);
else if (TREE_OPERAND ($$, 1) == NULL_TREE)
TREE_OPERAND ($$, 1) = arg;
else
$$ = build_parse_node (SCOPE_REF, $$, arg);
} }
| direct_abstract_declarator %prec EMPTY | direct_abstract_declarator %prec EMPTY
; ;
/* ANSI direct-abstract-declarator (8.1) */ /* ANSI direct-abstract-declarator (8.1) */
direct_abstract_declarator: direct_abstract_declarator:
'(' absdcl1 ')' '(' absdcl ')'
{ see_typename (); { $$ = $2; }
$$ = $2; }
/* `(typedef)1' is `int'. */ /* `(typedef)1' is `int'. */
| PAREN_STAR_PAREN | PAREN_STAR_PAREN
{ see_typename (); }
| direct_abstract_declarator '(' parmlist ')' type_quals %prec '.' | direct_abstract_declarator '(' parmlist ')' type_quals %prec '.'
{ $$ = build_parse_node (CALL_EXPR, $$, $3, $5); } { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); }
| direct_abstract_declarator LEFT_RIGHT type_quals %prec '.' | direct_abstract_declarator LEFT_RIGHT type_quals %prec '.'
...@@ -3813,11 +3590,6 @@ label_colon: ...@@ -3813,11 +3590,6 @@ label_colon:
} }
| PTYPENAME ':' | PTYPENAME ':'
{ goto do_label; } { 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 try_head: TRY '{' { cplus_expand_start_try (0); } .pushlevel
...@@ -4160,23 +3932,17 @@ named_parm: ...@@ -4160,23 +3932,17 @@ named_parm:
/* Here we expand typed_declspecs inline to avoid mis-parsing of /* Here we expand typed_declspecs inline to avoid mis-parsing of
TYPESPEC IDENTIFIER. */ TYPESPEC IDENTIFIER. */
typed_declspecs1 declarator typed_declspecs1 declarator
{ $$ = build_tree_list ($$, $2); { $$ = build_tree_list ($$, $2); }
see_typename (); }
| typed_typespecs declarator | typed_typespecs declarator
{ $$ = build_tree_list ($$, $2); { $$ = build_tree_list ($$, $2); }
see_typename (); }
| typespec declarator | typespec declarator
{ $$ = build_tree_list (get_decl_list ($$), $2); { $$ = build_tree_list (get_decl_list ($$), $2); }
see_typename (); }
| typed_declspecs1 absdcl | typed_declspecs1 absdcl
{ $$ = build_tree_list ($$, $2); { $$ = build_tree_list ($$, $2); }
see_typename (); }
| typed_declspecs1 %prec EMPTY | typed_declspecs1 %prec EMPTY
{ $$ = build_tree_list ($$, NULL_TREE); { $$ = build_tree_list ($$, NULL_TREE); }
see_typename (); }
| declmods notype_declarator | declmods notype_declarator
{ $$ = build_tree_list ($$, $2); { $$ = build_tree_list ($$, $2); }
see_typename (); }
; ;
parm: parm:
...@@ -4235,13 +4001,10 @@ raise_identifier: ...@@ -4235,13 +4001,10 @@ raise_identifier:
{ $$ = build_decl_list (NULL_TREE, $$); } { $$ = build_decl_list (NULL_TREE, $$); }
| TYPENAME | TYPENAME
{ $$ = build_decl_list (NULL_TREE, $$); } { $$ = build_decl_list (NULL_TREE, $$); }
| SCOPE IDENTIFIER | global_scope IDENTIFIER
{ $$ = build_decl_list (void_type_node, $2); } { $$ = build_decl_list (NULL_TREE, $2); }
| SCOPE TYPENAME | global_scope TYPENAME
{ $$ = build_decl_list (void_type_node, $2); } { $$ = build_decl_list (NULL_TREE, $2); }
| id_scope IDENTIFIER
{ $$ = build_decl_list ($$, $2); }
| scoped_typename
; ;
ansi_raise_identifier: ansi_raise_identifier:
...@@ -4274,87 +4037,87 @@ conversion_declarator: ...@@ -4274,87 +4037,87 @@ conversion_declarator:
{ $$ = make_pointer_declarator ($2, $3); } { $$ = make_pointer_declarator ($2, $3); }
| '&' type_quals conversion_declarator | '&' type_quals conversion_declarator
{ $$ = make_reference_declarator ($2, $3); } { $$ = make_reference_declarator ($2, $3); }
| id_scope '*' type_quals conversion_declarator | ptr_to_mem type_quals conversion_declarator
{ tree arg = make_pointer_declarator ($3, $4); { tree arg = make_pointer_declarator ($2, $3);
if (TREE_CODE ($$) != SCOPE_REF) $$ = build_parse_node (SCOPE_REF, $1, arg);
$$ = build_push_scope ($$, arg);
else if (TREE_OPERAND ($$, 1) == NULL_TREE)
TREE_OPERAND ($$, 1) = arg;
else
$$ = build_parse_node (SCOPE_REF, $$, arg);
} }
; ;
operator: OPERATOR
{ got_scope = NULL_TREE; }
;
operator_name: operator_name:
OPERATOR '*' operator '*'
{ $$ = ansi_opname[MULT_EXPR]; } { $$ = ansi_opname[MULT_EXPR]; }
| OPERATOR '/' | operator '/'
{ $$ = ansi_opname[TRUNC_DIV_EXPR]; } { $$ = ansi_opname[TRUNC_DIV_EXPR]; }
| OPERATOR '%' | operator '%'
{ $$ = ansi_opname[TRUNC_MOD_EXPR]; } { $$ = ansi_opname[TRUNC_MOD_EXPR]; }
| OPERATOR '+' | operator '+'
{ $$ = ansi_opname[PLUS_EXPR]; } { $$ = ansi_opname[PLUS_EXPR]; }
| OPERATOR '-' | operator '-'
{ $$ = ansi_opname[MINUS_EXPR]; } { $$ = ansi_opname[MINUS_EXPR]; }
| OPERATOR '&' | operator '&'
{ $$ = ansi_opname[BIT_AND_EXPR]; } { $$ = ansi_opname[BIT_AND_EXPR]; }
| OPERATOR '|' | operator '|'
{ $$ = ansi_opname[BIT_IOR_EXPR]; } { $$ = ansi_opname[BIT_IOR_EXPR]; }
| OPERATOR '^' | operator '^'
{ $$ = ansi_opname[BIT_XOR_EXPR]; } { $$ = ansi_opname[BIT_XOR_EXPR]; }
| OPERATOR '~' | operator '~'
{ $$ = ansi_opname[BIT_NOT_EXPR]; } { $$ = ansi_opname[BIT_NOT_EXPR]; }
| OPERATOR ',' | operator ','
{ $$ = ansi_opname[COMPOUND_EXPR]; } { $$ = ansi_opname[COMPOUND_EXPR]; }
| OPERATOR ARITHCOMPARE | operator ARITHCOMPARE
{ $$ = ansi_opname[$2]; } { $$ = ansi_opname[$2]; }
| OPERATOR '<' | operator '<'
{ $$ = ansi_opname[LT_EXPR]; } { $$ = ansi_opname[LT_EXPR]; }
| OPERATOR '>' | operator '>'
{ $$ = ansi_opname[GT_EXPR]; } { $$ = ansi_opname[GT_EXPR]; }
| OPERATOR EQCOMPARE | operator EQCOMPARE
{ $$ = ansi_opname[$2]; } { $$ = ansi_opname[$2]; }
| OPERATOR ASSIGN | operator ASSIGN
{ $$ = ansi_assopname[$2]; } { $$ = ansi_assopname[$2]; }
| OPERATOR '=' | operator '='
{ $$ = ansi_opname [MODIFY_EXPR]; } { $$ = ansi_opname [MODIFY_EXPR]; }
| OPERATOR LSHIFT | operator LSHIFT
{ $$ = ansi_opname[$2]; } { $$ = ansi_opname[$2]; }
| OPERATOR RSHIFT | operator RSHIFT
{ $$ = ansi_opname[$2]; } { $$ = ansi_opname[$2]; }
| OPERATOR PLUSPLUS | operator PLUSPLUS
{ $$ = ansi_opname[POSTINCREMENT_EXPR]; } { $$ = ansi_opname[POSTINCREMENT_EXPR]; }
| OPERATOR MINUSMINUS | operator MINUSMINUS
{ $$ = ansi_opname[PREDECREMENT_EXPR]; } { $$ = ansi_opname[PREDECREMENT_EXPR]; }
| OPERATOR ANDAND | operator ANDAND
{ $$ = ansi_opname[TRUTH_ANDIF_EXPR]; } { $$ = ansi_opname[TRUTH_ANDIF_EXPR]; }
| OPERATOR OROR | operator OROR
{ $$ = ansi_opname[TRUTH_ORIF_EXPR]; } { $$ = ansi_opname[TRUTH_ORIF_EXPR]; }
| OPERATOR '!' | operator '!'
{ $$ = ansi_opname[TRUTH_NOT_EXPR]; } { $$ = ansi_opname[TRUTH_NOT_EXPR]; }
| OPERATOR '?' ':' | operator '?' ':'
{ $$ = ansi_opname[COND_EXPR]; } { $$ = ansi_opname[COND_EXPR]; }
| OPERATOR MIN_MAX | operator MIN_MAX
{ $$ = ansi_opname[$2]; } { $$ = ansi_opname[$2]; }
| OPERATOR POINTSAT %prec EMPTY | operator POINTSAT %prec EMPTY
{ $$ = ansi_opname[COMPONENT_REF]; } { $$ = ansi_opname[COMPONENT_REF]; }
| OPERATOR POINTSAT_STAR %prec EMPTY | operator POINTSAT_STAR %prec EMPTY
{ $$ = ansi_opname[MEMBER_REF]; } { $$ = ansi_opname[MEMBER_REF]; }
| OPERATOR LEFT_RIGHT | operator LEFT_RIGHT
{ $$ = ansi_opname[CALL_EXPR]; } { $$ = ansi_opname[CALL_EXPR]; }
| OPERATOR '[' ']' | operator '[' ']'
{ $$ = ansi_opname[ARRAY_REF]; } { $$ = ansi_opname[ARRAY_REF]; }
| OPERATOR NEW | operator NEW %prec EMPTY
{ $$ = ansi_opname[NEW_EXPR]; } { $$ = ansi_opname[NEW_EXPR]; }
| OPERATOR DELETE | operator DELETE %prec EMPTY
{ $$ = ansi_opname[DELETE_EXPR]; } { $$ = ansi_opname[DELETE_EXPR]; }
/* | OPERATOR NEW '[' ']' | operator NEW '[' ']'
{ $$ = ansi_opname[VEC_NEW_EXPR]; } { $$ = ansi_opname[VEC_NEW_EXPR]; }
| OPERATOR DELETE '[' ']' | operator DELETE '[' ']'
{ $$ = ansi_opname[VEC_DELETE_EXPR]; } */ { $$ = ansi_opname[VEC_DELETE_EXPR]; }
| OPERATOR typed_typespecs conversion_declarator /* Should we be pushing into class scope to parse this? */
| operator typed_typespecs conversion_declarator
{ $$ = grokoptypename ($2, $3); } { $$ = grokoptypename ($2, $3); }
| OPERATOR error | operator error
{ $$ = ansi_opname[ERROR_MARK]; } { $$ = ansi_opname[ERROR_MARK]; }
; ;
......
...@@ -1690,6 +1690,7 @@ instantiate_template (tmpl, targ_ptr) ...@@ -1690,6 +1690,7 @@ instantiate_template (tmpl, targ_ptr)
return fndecl; return fndecl;
} }
/* classlevel should now never be true. jason 4/12/94 */
void void
undo_template_name_overload (id, classlevel) undo_template_name_overload (id, classlevel)
tree id; tree id;
...@@ -1711,6 +1712,7 @@ undo_template_name_overload (id, classlevel) ...@@ -1711,6 +1712,7 @@ undo_template_name_overload (id, classlevel)
#endif #endif
} }
/* classlevel should now never be true. jason 4/12/94 */
void void
overload_template_name (id, classlevel) overload_template_name (id, classlevel)
tree id; tree id;
...@@ -1731,12 +1733,9 @@ overload_template_name (id, classlevel) ...@@ -1731,12 +1733,9 @@ overload_template_name (id, classlevel)
#if 1 /* XXX */ #if 1 /* XXX */
/* This was a botch... names of templates do not get their own private /* This was a botch... names of templates do not get their own private
scopes. Rather, the names of generated template instances should scopes. Rather, they should go into the binding level already created
just get pushed into whatever scope we happen to be in at the moment. by push_template_decls. Except that there isn't one of those for
This will typically (but not always) be the global scope. (Maybe specializations. */
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.) */
if (!classlevel) if (!classlevel)
{ {
pushlevel (1); pushlevel (1);
...@@ -1765,20 +1764,13 @@ overload_template_name (id, classlevel) ...@@ -1765,20 +1764,13 @@ overload_template_name (id, classlevel)
if (classlevel) if (classlevel)
pushdecl_class_level (decl); pushdecl_class_level (decl);
else else
#if 0 /* not yet, should get fixed properly later */
pushdecl (decl); 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 /* Fake this for now, just to make dwarfout.c happy. It will have to
be done in a proper way later on. */ be done in a proper way later on. */
DECL_CONTEXT (decl) = t; DECL_CONTEXT (decl) = t;
#endif
} }
/* NAME is the IDENTIFIER value of a PRE_PARSED_CLASS_DECL. */ /* NAME is the IDENTIFIER value of a PRE_PARSED_CLASS_DECL. */
...@@ -2028,6 +2020,22 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) ...@@ -2028,6 +2020,22 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
return 0; return 0;
else if (targs[idx]) 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); my_friendly_abort (87);
return 1; return 1;
} }
...@@ -2306,3 +2314,18 @@ do_function_instantiation (declspecs, declarator) ...@@ -2306,3 +2314,18 @@ do_function_instantiation (declspecs, declarator)
if (!result) if (!result)
cp_error ("no matching template for `%D' found", decl); 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;
}
...@@ -108,10 +108,14 @@ print_lang_type (file, node, indent) ...@@ -108,10 +108,14 @@ print_lang_type (file, node, indent)
else else
fputs (" X(X&)", file); fputs (" X(X&)", file);
} }
if (TREE_GETS_NEW (node)) if (TYPE_GETS_NEW (node) & 1)
fputs (" gets-new", file); fputs (" new", file);
if (TREE_GETS_DELETE (node)) if (TYPE_GETS_NEW (node) & 2)
fputs (" gets-delete", file); 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)) if (TYPE_HAS_ASSIGNMENT (node))
fputs (" has=", file); fputs (" has=", file);
if (TYPE_HAS_ASSIGN_REF (node)) if (TYPE_HAS_ASSIGN_REF (node))
......
...@@ -1079,16 +1079,16 @@ lookup_field (xbasetype, name, protect, want_type) ...@@ -1079,16 +1079,16 @@ lookup_field (xbasetype, name, protect, want_type)
if (TREE_CODE (rval) == CONST_DECL) if (TREE_CODE (rval) == CONST_DECL)
{ {
if (this_v == access_private) 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) 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 else
{ {
if (this_v == access_private) 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) 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) ...@@ -1214,7 +1214,7 @@ lookup_field (xbasetype, name, protect, want_type)
else else
{ {
/* This is ambiguous. */ /* This is ambiguous. */
errstr = "request for member `%s' is ambiguous"; errstr = "request for member `%D' is ambiguous";
protect = 2; protect = 2;
break; break;
} }
...@@ -1250,7 +1250,7 @@ lookup_field (xbasetype, name, protect, want_type) ...@@ -1250,7 +1250,7 @@ lookup_field (xbasetype, name, protect, want_type)
new_v = compute_access (TREE_VALUE (TREE_CHAIN (*tp)), rval); new_v = compute_access (TREE_VALUE (TREE_CHAIN (*tp)), rval);
if (this_v != access_default && new_v != this_v) 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; this_v = access_default;
} }
own_access = new_v; own_access = new_v;
...@@ -1272,17 +1272,17 @@ lookup_field (xbasetype, name, protect, want_type) ...@@ -1272,17 +1272,17 @@ lookup_field (xbasetype, name, protect, want_type)
if (errstr == 0) if (errstr == 0)
{ {
if (own_access == access_private) if (own_access == access_private)
errstr = "member `%s' declared private"; errstr = "member `%D' declared private";
else if (own_access == access_protected) else if (own_access == access_protected)
errstr = "member `%s' declared protected"; errstr = "member `%D' declared protected";
else if (this_v == access_private) else if (this_v == access_private)
errstr = TREE_PRIVATE (rval) errstr = TREE_PRIVATE (rval)
? "member `%s' is private" ? "member `%D' is private"
: "member `%s' is from private base class"; : "member `%D' is from private base class";
else if (this_v == access_protected) else if (this_v == access_protected)
errstr = TREE_PROTECTED (rval) errstr = TREE_PROTECTED (rval)
? "member `%s' is protected" ? "member `%D' is protected"
: "member `%s' is from protected base class"; : "member `%D' is from protected base class";
} }
if (entry) if (entry)
...@@ -1302,17 +1302,7 @@ lookup_field (xbasetype, name, protect, want_type) ...@@ -1302,17 +1302,7 @@ lookup_field (xbasetype, name, protect, want_type)
if (errstr && protect) if (errstr && protect)
{ {
char *p = IDENTIFIER_POINTER (name), *q = NULL; cp_error (errstr, name, type);
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);
rval = error_mark_node; rval = error_mark_node;
} }
return rval; return rval;
...@@ -3031,15 +3021,15 @@ push_class_decls (type) ...@@ -3031,15 +3021,15 @@ push_class_decls (type)
search_stack = push_search_level (search_stack, &search_obstack); search_stack = push_search_level (search_stack, &search_obstack);
id = TYPE_IDENTIFIER (type); id = TYPE_IDENTIFIER (type);
#if 0
if (IDENTIFIER_TEMPLATE (id) != 0) if (IDENTIFIER_TEMPLATE (id) != 0)
{ {
#if 0
tree tmpl = IDENTIFIER_TEMPLATE (id); tree tmpl = IDENTIFIER_TEMPLATE (id);
push_template_decls (DECL_ARGUMENTS (TREE_PURPOSE (tmpl)), push_template_decls (DECL_ARGUMENTS (TREE_PURPOSE (tmpl)),
TREE_VALUE (tmpl), 1); TREE_VALUE (tmpl), 1);
#endif
overload_template_name (id, 1); overload_template_name (id, 1);
} }
#endif
/* Push class fields into CLASS_VALUE scope, and mark. */ /* Push class fields into CLASS_VALUE scope, and mark. */
dfs_walk (TYPE_BINFO (type), dfs_pushdecls, unmarkedp); dfs_walk (TYPE_BINFO (type), dfs_pushdecls, unmarkedp);
...@@ -3227,3 +3217,27 @@ reinit_search_statistics () ...@@ -3227,3 +3217,27 @@ reinit_search_statistics ()
n_outer_fields_searched = 0; n_outer_fields_searched = 0;
n_contexts_saved = 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;
}
...@@ -45,12 +45,6 @@ struct token { ...@@ -45,12 +45,6 @@ struct token {
}; };
static int do_aggr (); 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: */ /* From lex.c: */
/* the declaration found for the last IDENTIFIER token read in. /* the declaration found for the last IDENTIFIER token read in.
...@@ -72,51 +66,10 @@ static unsigned int yylex_ctr = 0; ...@@ -72,51 +66,10 @@ static unsigned int yylex_ctr = 0;
static int debug_yychar (); static int debug_yychar ();
#endif #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. */ /* Initialize token_obstack. Called once, from init_lex. */
void void
init_spew () 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); gcc_obstack_init(&token_obstack);
} }
...@@ -181,7 +134,8 @@ consume_token() ...@@ -181,7 +134,8 @@ consume_token()
: first_token++) : first_token++)
#endif #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 static void
scan_tokens (n) scan_tokens (n)
...@@ -278,13 +232,13 @@ probe_obstack (h, obj, nlevels) ...@@ -278,13 +232,13 @@ probe_obstack (h, obj, nlevels)
} }
/* from lex.c: */ /* from lex.c: */
/* Value is 1 if we should try to make the next identifier look like a /* Value is 1 (or 2) if we should try to make the next identifier look like
typename (when it may be a local variable or a class variable). 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 0 if we treat this name in a default fashion. */
Value is -1 if we must not see a type name. */
extern int looking_for_typename; extern int looking_for_typename;
extern struct obstack *current_obstack, *saveable_obstack; extern struct obstack *current_obstack, *saveable_obstack;
tree got_scope;
int int
yylex() yylex()
...@@ -300,36 +254,6 @@ yylex() ...@@ -300,36 +254,6 @@ yylex()
fprintf(stderr, "\t\t## %d ##",yylex_ctr); fprintf(stderr, "\t\t## %d ##",yylex_ctr);
} }
#endif #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 we've got tokens, send them */
if (num_tokens()) if (num_tokens())
...@@ -370,7 +294,13 @@ yylex() ...@@ -370,7 +294,13 @@ yylex()
goto retry; goto retry;
case IDENTIFIER: 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); trrr = lookup_name (tmp_token.yylval.ttype, -2);
if (trrr) if (trrr)
{ {
tmp_token.yychar = identifier_type (trrr); tmp_token.yychar = identifier_type (trrr);
...@@ -378,28 +308,17 @@ yylex() ...@@ -378,28 +308,17 @@ yylex()
{ {
case TYPENAME: case TYPENAME:
lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype); lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype);
if (lastiddecl == NULL_TREE) if (lastiddecl != trrr)
lastiddecl = trrr; {
lastiddecl = trrr;
tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
}
break; break;
case IDENTIFIER: case IDENTIFIER:
lastiddecl = trrr; lastiddecl = trrr;
break; break;
case PTYPENAME: case PTYPENAME:
/* This is for cases like lastiddecl = NULL_TREE;
template<class A> X<A>::operator[] ...
since "X" is (presumably) a PTYPENAME; we might want to
avoid seeing the entire thing as a type name, but X<A>
must be one.
It might not work right if the thing after the ::
can be a typename nested in X<A>, 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;
}
break; break;
default: default:
my_friendly_abort (101); my_friendly_abort (101);
...@@ -410,120 +329,20 @@ yylex() ...@@ -410,120 +329,20 @@ yylex()
/* and fall through to... */ /* and fall through to... */
case TYPENAME: case TYPENAME:
case PTYPENAME: case PTYPENAME:
/* if (new_token) add_token (&tmp_token); */ consume_token ();
*nth_token(0) = tmp_token; if (looking_for_typename > 0)
tmp_token = frob_identifier (); looking_for_typename--;
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;
break; break;
case SCSPEC: case SCSPEC:
/* do_aggr needs to check if the previous token was RID_FRIEND, /* do_aggr needs to check if the previous token was RID_FRIEND,
so just increment first_token instead of calling consume_token. */ so just increment first_token instead of calling consume_token. */
first_token++; first_token++;
goto finish_typename_processing; break;
case TYPESPEC: case TYPESPEC:
consume_token (); 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; 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: case AGGR:
*nth_token(0) = tmp_token; *nth_token(0) = tmp_token;
do_aggr (); do_aggr ();
...@@ -533,36 +352,7 @@ yylex() ...@@ -533,36 +352,7 @@ yylex()
looking_for_typename = 1; looking_for_typename = 1;
/* fall through... */ /* fall through... */
default: default:
#ifdef SPEW_DEBUG
if (spew_debug)
debug_yychar(tmp_token.yychar);
#endif
consume_token(); 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; yylval = tmp_token.yylval;
...@@ -572,7 +362,6 @@ yylex() ...@@ -572,7 +362,6 @@ yylex()
if (spew_debug) if (spew_debug)
debug_yychar(yychar); debug_yychar(yychar);
#endif #endif
/* consume_token(); */ /* already eaten by frob_identifier?... */
return yychar; return yychar;
} }
...@@ -618,515 +407,6 @@ do_aggr () ...@@ -618,515 +407,6 @@ do_aggr ()
} }
return 0; 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; i<n; i++)
consume_token();
/* IDENTIFIER_TYPE_VALUE (DECL_NAME (tc)) = */
return DECL_NAME (tc);
}
return NULL_TREE;
}
#endif
#if 0
static tree
hack_more_ids (n)
int n;
{
/*
* The recursion should probably do consume_tokens(), since once we've started
* down an IDENTIFIER SCOPE ... chain, we don't need to back-track - we just
* get as much as we can, make SCOPE_REF's out of it, and return it.
*/
struct token this_iter, this2_iter;
int tmp_y;
scan_tokens(n+1);
this_iter = *nth_token(n);
tmp_y = nth_token(n)->yychar;
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 #ifdef SPEW_DEBUG
/* debug_yychar takes a yychar (token number) value and prints its name. */ /* debug_yychar takes a yychar (token number) value and prints its name. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment