`echo $(srcdir)/parse.c | sed 's,^\./,,'`
$(srcdir)/parse.c $(srcdir)/parse.h : $(srcdir)/parse.y
- @echo expect 24 reduce/reduce conflicts.
+ @echo expect 33 reduce/reduce conflicts.
cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y
cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h
{
/* Explicit call to destructor. */
name = TREE_OPERAND (name, 0);
- if (TREE_TYPE (decl) !=
- (IDENTIFIER_CLASS_VALUE (name)
- ? IDENTIFIER_CLASS_TYPE_VALUE (name)
- : IDENTIFIER_TYPE_VALUE (name)))
+ if (name != constructor_name (TREE_TYPE (decl)))
{
cp_error
("qualified type `%T' does not match destructor type `%T'",
/* If it doesn't work, two argument delete must work */
TREE_CHAIN (parms) = save_last;
}
+ /* We already know whether it's needed or not for vec delete. */
+ else if (name == ansi_opname[(int) VEC_DELETE_EXPR]
+ && ! TYPE_VEC_DELETE_TAKES_SIZE (TREE_TYPE (instance)))
+ TREE_CHAIN (parms) = NULL_TREE;
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
for (x = *testp; x; x = DECL_CHAIN (x))
{
- if (DECL_NAME (fn_fields) == ansi_opname[(int) DELETE_EXPR])
+ if (DECL_NAME (fn_fields) == ansi_opname[(int) DELETE_EXPR]
+ || DECL_NAME (fn_fields)
+ == ansi_opname[(int) VEC_DELETE_EXPR])
{
/* ANSI C++ June 5 1992 WP 12.5.5.1 */
cp_error_at ("`%D' overloaded", fn_fields);
else if (flag_dossier && ! CLASSTYPE_DOSSIER (t))
build_t_desc (t, 1);
+#if 0
if (TYPE_NAME (t) && TYPE_IDENTIFIER (t))
undo_template_name_overload (TYPE_IDENTIFIER (t), 1);
+#endif
if (current_class_type)
popclass (0);
else
current_function_decl = NULL_TREE;
if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
- {
- declare_uninstantiated_type_level ();
- overload_template_name (current_class_name, 0);
- }
+ declare_uninstantiated_type_level ();
else if (type != previous_class_type || current_class_depth > 1)
{
build_mi_matrix (type);
unuse_fields (type);
}
+ if (IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (type)))
+ overload_template_name (current_class_name, 0);
+
for (tags = CLASSTYPE_TAGS (type); tags; tags = TREE_CHAIN (tags))
{
TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 1;
TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0;
tags = TREE_CHAIN (tags);
}
+ if (IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type)))
+ undo_template_name_overload (current_class_name, 0);
}
- if (TREE_CODE (current_class_type) == UNINSTANTIATED_P_TYPE)
- undo_template_name_overload (current_class_name, 0);
poplevel_class ();
tree type;
int modify;
{
- tree context = DECL_CONTEXT (TYPE_NAME (type));
+ tree context;
+
+ if (type == error_mark_node || ! IS_AGGR_TYPE (type))
+ return;
+
+ context = DECL_CONTEXT (TYPE_NAME (type));
if (context && TREE_CODE (context) == RECORD_TYPE)
push_nested_class (context, 2);
Operand 1 is the value to pass to the destroying function
saying whether the store should be deallocated as well. */
DEFTREECODE (DELETE_EXPR, "dl_expr", "e", 2)
+DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", "e", 2)
/* Value is reference to particular overloaded class method.
Operand 0 is the class name (an IDENTIFIER_NODE);
operand 1 is argument list to initialization function,
and operand 2 is the slot which was allocated for this expression. */
DEFTREECODE (NEW_EXPR, "nw_expr", "e", 3)
+DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", "e", 3)
/* Distinguish variables that are only used to identify exceptions
that were caught. Only the DECL_NAME (and TREE_CHAIN)
#define IDENTIFIER_TYPE_VALUE(NODE) (TREE_TYPE (NODE))
#define SET_IDENTIFIER_TYPE_VALUE(NODE,TYPE) (TREE_TYPE (NODE) = TYPE)
#define IDENTIFIER_HAS_TYPE_VALUE(NODE) (TREE_TYPE (NODE) ? 1 : 0)
-#define IDENTIFIER_HAS_CLASS_TYPE_VALUE(NODE) \
- (IDENTIFIER_CLASS_VALUE (NODE) && TREE_TYPE (IDENTIFIER_CLASS_VALUE (NODE)))
-#define IDENTIFIER_CLASS_TYPE_VALUE(NODE) \
- TREE_TYPE (IDENTIFIER_CLASS_VALUE (NODE))
#define LANG_ID_FIELD(NAME,NODE) \
(((struct lang_identifier *)(NODE))->x \
#define TYPE_ASSEMBLER_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE))))
#define IS_AGGR_TYPE(t) (TYPE_LANG_FLAG_5 (t))
-#define IS_AGGR_TYPE_CODE(t) (t == RECORD_TYPE || t == UNION_TYPE)
+#define IS_AGGR_TYPE_CODE(t) (t == RECORD_TYPE || t == UNION_TYPE || t == UNINSTANTIATED_P_TYPE)
#define IS_AGGR_TYPE_2(TYPE1,TYPE2) \
(TREE_CODE (TYPE1) == TREE_CODE (TYPE2) \
&& IS_AGGR_TYPE (TYPE1)&IS_AGGR_TYPE (TYPE2))
unsigned vtable_needs_writing : 1;
unsigned has_assign_ref : 1;
- unsigned gets_new : 1;
- unsigned gets_placed_new : 1;
- unsigned gets_delete : 1;
+ unsigned gets_new : 2;
+ unsigned gets_delete : 2;
unsigned has_call_overloaded : 1;
unsigned has_array_ref_overloaded : 1;
unsigned has_arrow_overloaded : 1;
- unsigned local_typedecls : 1;
+ unsigned local_typedecls : 1;
unsigned interface_only : 1;
unsigned interface_unknown : 1;
unsigned needs_virtual_reinit : 1;
unsigned declared_class : 1;
unsigned being_defined : 1;
unsigned redefined : 1;
- unsigned no_globalize : 1;
+ unsigned no_globalize : 1;
unsigned marked : 1;
unsigned marked2 : 1;
unsigned marked3 : 1;
unsigned marked4 : 1;
unsigned marked5 : 1;
unsigned marked6 : 1;
- unsigned use_template : 2;
+ unsigned use_template : 2;
unsigned debug_requested : 1;
unsigned has_method_call_overloaded : 1;
unsigned private_attr : 1;
unsigned ptrmemfunc_flag : 1;
unsigned is_signature : 1;
unsigned is_signature_pointer : 1;
- unsigned is_signature_reference : 1;
+ unsigned is_signature_reference : 1;
unsigned has_default_implementation : 1;
unsigned grokking_typedef : 1;
unsigned has_opaque_typedecls : 1;
unsigned was_anonymous : 1;
unsigned has_real_assignment : 1;
unsigned has_real_assign_ref : 1;
+
unsigned has_const_init_ref : 1;
-
unsigned has_complex_init_ref : 1;
unsigned has_complex_assign_ref : 1;
+ unsigned vec_delete_takes_size : 1;
/* The MIPS compiler gets it wrong if this struct also
does not fill out to a multiple of 4 bytes. Add a
member `dummy' with new bits if you go over the edge. */
- unsigned dummy : 22;
+ unsigned dummy : 20;
unsigned n_vancestors : 16;
} type_flags;
/* Nonzero for _CLASSTYPE means that operator new and delete are defined,
respectively. */
-#define TREE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_new)
-#define TREE_GETS_PLACED_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_placed_new)
-#define TREE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_delete)
+#define TYPE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_new)
+#define TYPE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_delete)
+#define TYPE_GETS_REG_DELETE(NODE) (TYPE_GETS_DELETE (NODE) & 1)
+
+/* Nonzero for _CLASSTYPE means that operator vec delete is defined and
+ takes the optional size_t argument. */
+#define TYPE_VEC_DELETE_TAKES_SIZE(NODE) \
+ (TYPE_LANG_SPECIFIC(NODE)->type_flags.vec_delete_takes_size)
+#define TYPE_VEC_NEW_USES_COOKIE(NODE) \
+ (TYPE_NEEDS_DESTRUCTOR (NODE) \
+ || (TYPE_LANG_SPECIFIC (NODE) && TYPE_VEC_DELETE_TAKES_SIZE (NODE)))
/* Nonzero for TREE_LIST or _TYPE node means that this node is class-local. */
#define TREE_NONLOCAL_FLAG(NODE) (TREE_LANG_FLAG_0 (NODE))
extern tree build_x_delete PROTO((tree, tree, int, tree));
extern tree build_delete PROTO((tree, tree, tree, int, int));
extern tree build_vbase_delete PROTO((tree, tree));
-extern tree build_vec_delete PROTO((tree, tree, tree, tree, tree, tree));
+extern tree build_vec_delete PROTO((tree, tree, tree, tree, tree, int));
/* in input.c */
extern void do_pending_templates PROTO((void));
struct tinst_level *tinst_for_decl PROTO((void));
extern void do_function_instantiation PROTO((tree, tree));
+extern tree create_nested_upt PROTO((tree, tree));
/* in search.c */
extern tree make_memoized_table_entry PROTO((tree, tree, int));
extern tree lookup_field PROTO((tree, tree, int, int));
extern tree lookup_nested_field PROTO((tree, int));
extern tree lookup_fnfields PROTO((tree, tree, int));
+extern tree lookup_nested_tag PROTO((tree, tree));
extern HOST_WIDE_INT breadth_first_search PROTO((tree, int (*)(), int (*)()));
extern int tree_needs_constructor_p PROTO((tree, int));
extern int tree_has_any_destructor_p PROTO((tree, int));
extern tree common_base_types PROTO((tree, tree));
extern int compparms PROTO((tree, tree, int));
extern int comp_target_types PROTO((tree, tree, int));
+extern int self_promoting_args_p PROTO((tree));
extern tree unsigned_type PROTO((tree));
extern tree signed_type PROTO((tree));
extern tree signed_or_unsigned_type PROTO((int, tree));
{
/* When casting an lvalue to a reference type, just convert into
a pointer to the new type and deference it. This is allowed
- by San Diego WP section 5.2.8 paragraph 9, though perhaps it
+ by San Diego WP section 5.2.9 paragraph 12, though perhaps it
should be done directly (jason). (int &)ri ---> *(int*)&ri */
+
+ /* B* bp; A& ar = (A&)bp; is legal, but it's probably not what they
+ meant. */
+ if (form == POINTER_TYPE
+ && (comptypes (TREE_TYPE (intype), type, strict)))
+ cp_warning ("casting `%T' to `%T' does not dereference pointer",
+ intype, reftype);
+
rval = build_unary_op (ADDR_EXPR, expr, 0);
if (rval != error_mark_node)
rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval);
/* Definitely need to go through a constructor here. */
if (TYPE_HAS_CONSTRUCTOR (type)
+ && ! CLASSTYPE_ABSTRACT_VIRTUALS (type)
&& (rval = build_method_call
(NULL_TREE, constructor_name_full (type),
build_tree_list (NULL_TREE, expr), TYPE_BINFO (type),
{
int types_match;
- if (TREE_CODE (newdecl) == FUNCTION_DECL && TREE_CODE (olddecl) == FUNCTION_DECL)
+ if (TREE_CODE (newdecl) == FUNCTION_DECL
+ && TREE_CODE (olddecl) == FUNCTION_DECL)
{
tree f1 = TREE_TYPE (newdecl);
tree f2 = TREE_TYPE (olddecl);
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (f1)),
TYPE_MAIN_VARIANT (TREE_TYPE (f2)), 2))
{
- if (DECL_LANGUAGE (olddecl) == lang_c
- && ! strict_prototypes_lang_c
+ if (! strict_prototypes_lang_c && DECL_LANGUAGE (olddecl) == lang_c
&& p2 == NULL_TREE)
- types_match = self_promoting_args_p (p1);
+ {
+ types_match = self_promoting_args_p (p1);
+ if (p1 == void_list_node)
+ TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
+ }
+ else if (!strict_prototypes_lang_c && DECL_LANGUAGE (olddecl)==lang_c
+ && DECL_LANGUAGE (newdecl) == lang_c && p1 == NULL_TREE)
+ {
+ types_match = self_promoting_args_p (p2);
+ TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
+ }
else
types_match = compparms (p1, p2, 1);
}
int foo () { bar (); }
is OK. */
if (current_lang_stack == current_lang_base)
- {
- DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl);
- if (TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == NULL_TREE
- && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) == void_list_node)
- TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
- }
+ DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl);
else
{
cp_error_at ("previous declaration of `%#D' with %L linkage",
if (pedantic
&& (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)
|| TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl)))
- cp_error_at ("type qualifiers for `%D' conflict with previous decl", newdecl);
+ cp_error_at ("type qualifiers for `%D' conflict with previous decl",
+ newdecl);
}
/* If new decl is `static' and an `extern' was seen previously,
} Thing;
*/
#if 0
- my_friendly_assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl), 139);
+ my_friendly_assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl),
+ 139);
#endif
}
TREE_TYPE (olddecl) = build_exception_variant (ctype, newtype,
TYPE_RAISES_EXCEPTIONS (oldtype));
- if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE(olddecl), 0))
+ if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0))
{
- cp_error ("declaration of `%D' raises different exceptions...", newdecl);
+ cp_error ("declaration of `%D' raises different exceptions...",
+ newdecl);
cp_error_at ("...from previous declaration here", olddecl);
}
}
if (extra_warnings)
{
- cp_warning ("`static' missing from declaration of `%D'", t);
+ cp_warning ("`static' missing from declaration of `%D'",
+ t);
warning_with_file_and_line (file, line,
"previous declaration of `%s'",
decl_as_string (t, 0));
{
if (decl == tmp || duplicate_decls (decl, tmp))
return tmp;
- if (compparms (TYPE_ARG_TYPES (TREE_TYPE (decl)),
- TYPE_ARG_TYPES (TREE_TYPE (tmp)), 2))
+ /* Avoid doing things about built-ins, since duplicate_decls
+ will have given warnings/errors for them. */
+ if (!DECL_BUILT_IN (tmp) && !DECL_BUILT_IN_NONANSI (tmp)
+ && compparms (TYPE_ARG_TYPES (TREE_TYPE (decl)),
+ TYPE_ARG_TYPES (TREE_TYPE (tmp)), 2))
{
cp_error ("new declaration `%#D'", decl);
cp_error_at ("ambiguates old declaration `%#D'", tmp);
}
break;
case FUNCTION_DECL:
- return TYPE_IDENTIFIER (type) ? lookup_name (TYPE_IDENTIFIER (type), 1) : NULL_TREE;
+ return TYPE_IDENTIFIER (type) ?
+ lookup_name (TYPE_IDENTIFIER (type), 1) : NULL_TREE;
break;
default:
my_friendly_abort (12);
definitions if there are many, or return 0 if it is undefined.
If PREFER_TYPE is > 0, we prefer TYPE_DECLs.
+ If PREFER_TYPE is -2, we're being called from yylex(). (UGLY)
Otherwise we prefer non-TYPE_DECLs. */
tree
int prefer_type;
{
register tree val;
+ int yylex = 0;
+ if (prefer_type == -2)
+ {
+ extern int looking_for_typename;
+
+ yylex = 1;
+ prefer_type = looking_for_typename;
+
+ if (got_scope != NULL_TREE)
+ {
+ if (got_scope == void_type_node)
+ val = IDENTIFIER_GLOBAL_VALUE (name);
+ else if (TREE_CODE (got_scope) == TEMPLATE_TYPE_PARM
+ /* TFIXME -- don't do this for UPTs in new model. */
+ || TREE_CODE (got_scope) == UNINSTANTIATED_P_TYPE)
+ {
+ if (prefer_type > 0)
+ val = create_nested_upt (got_scope, name);
+ else
+ val = NULL_TREE;
+ }
+ else if (! IS_AGGR_TYPE (got_scope))
+ /* Someone else will give an error about this if needed. */
+ val = NULL_TREE;
+ else if (got_scope == current_class_type)
+ val = IDENTIFIER_CLASS_VALUE (name);
+ else if (TYPE_BEING_DEFINED (got_scope))
+ val = lookup_nested_tag (got_scope, name);
+ else
+ val = lookup_field (got_scope, name, 0, 0);
+
+ got_scope = NULL_TREE;
+ goto done;
+ }
+ }
+
if (current_binding_level != global_binding_level
&& IDENTIFIER_LOCAL_VALUE (name))
val = IDENTIFIER_LOCAL_VALUE (name);
/* Try to find values from base classes
if we are presently defining a type.
We are presently only interested in TYPE_DECLs. */
- val = lookup_field (current_class_type, name, 0, prefer_type < 0);
+ val = lookup_field (current_class_type, name, 0, 1);
if (val == error_mark_node)
return val;
if (val && TREE_CODE (val) != TYPE_DECL)
the nested name at the point where we haven't even, for example,
created the COMPONENT_REF or anything like that. */
if (val == NULL_TREE)
- val = lookup_nested_field (name, prefer_type != -2);
+ val = lookup_nested_field (name, ! yylex);
if (val == NULL_TREE)
val = IDENTIFIER_GLOBAL_VALUE (name);
else
val = IDENTIFIER_GLOBAL_VALUE (name);
+ done:
if (val)
{
- extern int looking_for_typename;
-
/* Arbitrate between finding a TYPE_DECL and finding
other kinds of _DECLs. */
- if (TREE_CODE (val) == TYPE_DECL || looking_for_typename < 0)
+ if (TREE_CODE (val) == TYPE_DECL || prefer_type < 0)
return val;
if (IDENTIFIER_HAS_TYPE_VALUE (name))
{
register tree val_as_type = TYPE_NAME (IDENTIFIER_TYPE_VALUE (name));
- if (val == val_as_type || prefer_type > 0
- || looking_for_typename > 0)
+ if (val == val_as_type || prefer_type > 0)
return val_as_type;
return val;
error_mark_list = build_tree_list (error_mark_node, error_mark_node);
TREE_TYPE (error_mark_list) = error_mark_node;
- pushlevel (0); /* make the binding_level structure for global names. */
+ /* Make the binding_level structure for global names. */
+ pushlevel (0);
global_binding_level = current_binding_level;
this_identifier = get_identifier (THIS_NAME);
TREE_TYPE (void_zero_node) = void_type_node;
string_type_node = build_pointer_type (char_type_node);
- const_string_type_node = build_pointer_type (build_type_variant (char_type_node, 1, 0));
+ const_string_type_node =
+ build_pointer_type (build_type_variant (char_type_node, 1, 0));
record_builtin_type (RID_MAX, NULL_PTR, string_type_node);
/* Make a type to be the domain of a few array types
build_pointer_type (default_function_type);
ptr_type_node = build_pointer_type (void_type_node);
- const_ptr_type_node = build_pointer_type (build_type_variant (void_type_node, 1, 0));
+ const_ptr_type_node =
+ build_pointer_type (build_type_variant (void_type_node, 1, 0));
record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node);
endlink = void_list_node;
int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink);
double_ftype_double_double
= build_function_type (double_type_node,
- tree_cons (NULL_TREE, double_type_node, double_endlink));
+ tree_cons (NULL_TREE, double_type_node,
+ double_endlink));
int_ftype_int
= build_function_type (integer_type_node, int_endlink);
long_ftype_long
= build_function_type (long_integer_type_node,
- tree_cons (NULL_TREE, long_integer_type_node, endlink));
+ tree_cons (NULL_TREE, long_integer_type_node,
+ endlink));
void_ftype_ptr_ptr_int
= build_function_type (void_type_node,
builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP,
NULL_PTR);
builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, NULL_PTR);
- builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, NULL_PTR);
+ builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY,
+ NULL_PTR);
#if 0
/* Not yet. */
builtin_function ("strncpy", strncpy_ftype, BUILT_IN_STRNCPY, NULL_PTR);
or build_function_call. */
builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, 0);
builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, 0);
- builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR, 0);
+ builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR,
+ 0);
builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL, 0);
- builtin_function ("__builtin_fmod", double_ftype_double_double, BUILT_IN_FMOD, 0);
- builtin_function ("__builtin_frem", double_ftype_double_double, BUILT_IN_FREM, 0);
- builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, BUILT_IN_MEMSET, 0);
- builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP, 0);
- builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN, 0);
+ builtin_function ("__builtin_fmod", double_ftype_double_double,
+ BUILT_IN_FMOD, 0);
+ builtin_function ("__builtin_frem", double_ftype_double_double,
+ BUILT_IN_FREM, 0);
+ builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, BUILT_IN_MEMSET,
+ 0);
+ builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP,
+ 0);
+ builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN,
+ 0);
#endif
/* C++ extensions */
TYPE_MODE (unknown_type_node) = TYPE_MODE (void_type_node);
/* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */
TREE_TYPE (unknown_type_node) = unknown_type_node;
- /* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same result. */
+ /* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same result. */
TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
fields names so that the debugger can use them. */
memptr_type = make_lang_type (RECORD_TYPE);
- fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, delta_type_node);
- fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier, delta_type_node);
- fields[2] = build_lang_field_decl (FIELD_DECL, pfn_identifier, ptr_type_node);
+ fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
+ delta_type_node);
+ fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier,
+ delta_type_node);
+ fields[2] = build_lang_field_decl (FIELD_DECL, pfn_identifier,
+ ptr_type_node);
finish_builtin_type (memptr_type, VTBL_PTR_TYPE, fields, 2,
double_type_node);
if (flag_handle_signatures)
{
sigtable_entry_type = make_lang_type (RECORD_TYPE);
- fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier (SIGTABLE_CODE_NAME), short_integer_type_node);
- fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier (SIGTABLE_OFFSET_NAME), short_integer_type_node);
- fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier (SIGTABLE_PFN_NAME), ptr_type_node);
+ fields[0] = build_lang_field_decl (FIELD_DECL,
+ get_identifier (SIGTABLE_CODE_NAME),
+ short_integer_type_node);
+ fields[1] = build_lang_field_decl (FIELD_DECL,
+ get_identifier (SIGTABLE_OFFSET_NAME),
+ short_integer_type_node);
+ fields[2] = build_lang_field_decl (FIELD_DECL,
+ get_identifier (SIGTABLE_PFN_NAME),
+ ptr_type_node);
finish_builtin_type (sigtable_entry_type, SIGTABLE_PTR_TYPE, fields, 2,
double_type_node);
sigtable_entry_type = build_type_variant (sigtable_entry_type, 1, 0);
__t_desc_type_node = make_lang_type (RECORD_TYPE);
__i_desc_type_node = make_lang_type (RECORD_TYPE);
__m_desc_type_node = make_lang_type (RECORD_TYPE);
- __t_desc_array_type = build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE);
- __i_desc_array_type = build_array_type (TYPE_POINTER_TO (__i_desc_type_node), NULL_TREE);
- __m_desc_array_type = build_array_type (TYPE_POINTER_TO (__m_desc_type_node), NULL_TREE);
+ __t_desc_array_type =
+ build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE);
+ __i_desc_array_type =
+ build_array_type (TYPE_POINTER_TO (__i_desc_type_node), NULL_TREE);
+ __m_desc_array_type =
+ build_array_type (TYPE_POINTER_TO (__m_desc_type_node), NULL_TREE);
fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
string_type_node);
unsigned_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("bits"),
unsigned_type_node);
- fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("points_to"),
+ fields[3] = build_lang_field_decl (FIELD_DECL,
+ get_identifier ("points_to"),
TYPE_POINTER_TO (__t_desc_type_node));
fields[4] = build_lang_field_decl (FIELD_DECL,
get_identifier ("ivars_count"),
integer_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"),
TYPE_POINTER_TO (__t_desc_type_node));
- finish_builtin_type (__i_desc_type_node, "__i_desc", fields, 2, integer_type_node);
+ finish_builtin_type (__i_desc_type_node, "__i_desc", fields, 2,
+ integer_type_node);
/* method descriptors look like this:
short_integer_type_node);
fields[7] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_types"),
build_pointer_type (build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE)));
- finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7, integer_type_node);
+ finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7,
+ integer_type_node);
}
/* Now, C++. */
tree_cons (NULL_TREE, sizetype,
void_list_node)),
NOT_BUILT_IN);
+ auto_function (ansi_opname[(int) VEC_NEW_EXPR],
+ build_function_type (ptr_type_node,
+ tree_cons (NULL_TREE, sizetype,
+ void_list_node)),
+ NOT_BUILT_IN);
auto_function (ansi_opname[(int) DELETE_EXPR],
build_function_type (void_type_node,
tree_cons (NULL_TREE, ptr_type_node,
void_list_node)),
NOT_BUILT_IN);
+ auto_function (ansi_opname[(int) VEC_DELETE_EXPR],
+ build_function_type (void_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
+ void_list_node)),
+ NOT_BUILT_IN);
abort_fndecl
= define_function ("abort",
function members. */
if (TYPE_FIELDS (t))
{
- tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0, NULL_TREE);
+ tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
+ NULL_TREE);
finish_anon_union (decl);
}
else
/* This should only be done once on the top most decl. */
if (have_extern_spec && !used_extern_spec)
{
- declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);
+ declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"),
+ declspecs);
used_extern_spec = 1;
}
DECL_ARGUMENTS (decl) = args;
}
d = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), TREE_TYPE (decl));
- if (interface_unknown && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl))
+ if (interface_unknown && flag_external_templates
+ && ! DECL_IN_SYSTEM_HEADER (decl))
warn_if_unknown_interface ();
- TREE_PUBLIC (d) = TREE_PUBLIC (decl) = flag_external_templates && !interface_unknown;
+ TREE_PUBLIC (d) = TREE_PUBLIC (decl) =
+ flag_external_templates && !interface_unknown;
TREE_STATIC (d) = TREE_STATIC (decl);
DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl)
&& !(context && !DECL_THIS_EXTERN (decl)));
use temporary storage. Do this even if we will ignore the value. */
if (current_binding_level == global_binding_level && debug_temp_inits)
{
- if (TYPE_NEEDS_CONSTRUCTING (type) || TREE_CODE (type) == REFERENCE_TYPE)
+ if (TYPE_NEEDS_CONSTRUCTING (type)
+ || TREE_CODE (type) == REFERENCE_TYPE)
/* In this case, the initializer must lay down in permanent
storage, since it will be saved until `finish_file' is run. */
;
TREE_OPERAND (TREE_OPERAND (tmp, 0), 2) = error_mark_node;
}
if (IS_AGGR_TYPE (TREE_TYPE (this_ptr_type)))
- DECL_INITIAL (decl) = convert_pointer_to (TREE_TYPE (this_ptr_type), tmp);
+ DECL_INITIAL (decl) = convert_pointer_to (TREE_TYPE (this_ptr_type),
+ tmp);
else
DECL_INITIAL (decl) = convert (this_ptr_type, tmp);
if (TREE_CODE (actual_init) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (actual_init, 0)) == TARGET_EXPR)
actual_init = save_expr (actual_init);
- DECL_INITIAL (decl) = convert_pointer_to (TREE_TYPE (this_ptr_type), actual_init);
+ DECL_INITIAL (decl) = convert_pointer_to (TREE_TYPE (this_ptr_type),
+ actual_init);
DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
TREE_TYPE (DECL_INITIAL (decl)) = type;
}
{
if (TYPE_NEEDS_CONSTRUCTING (type))
{
- cp_error ("`%D' must be initialized by constructor, not by `{...}'", decl);
+ cp_error ("`%D' must be initialized by constructor, not by `{...}'",
+ decl);
init = error_mark_node;
}
else
if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (ctype))
cp_error ("structure `%D' with uninitialized const members", decl);
if (CLASSTYPE_REF_FIELDS_NEED_INIT (ctype))
- cp_error ("structure `%D' with uninitialized reference members", decl);
+ cp_error ("structure `%D' with uninitialized reference members",
+ decl);
}
if (TREE_CODE (decl) == VAR_DECL
}
else if (toplev)
{
- /* Keep GCC from complaining that this variable
- is defined but never used. */
- TREE_USED (decl) = 1;
/* If this is a static const, change its apparent linkage
if it belongs to a #pragma interface. */
if (TREE_STATIC (decl) && !interface_unknown)
: & TYPE_ARG_TYPES (type);
*argp = NULL_TREE;
- fnname = build_decl_overload (original_name, TYPE_ARG_TYPES (type), 0);
+ fnname = build_decl_overload (original_name,
+ TYPE_ARG_TYPES (type), 0);
*argp = parmtypes;
fndecl = build_decl (FUNCTION_DECL, fnname, type);
DECL_EXTERNAL (fndecl) = DECL_EXTERNAL (decl);
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);
}
if (cleanup)
{
if (! expand_decl_cleanup (decl, cleanup))
- cp_error ("parser lost in parsing declaration of `%D'", decl);
+ cp_error ("parser lost in parsing declaration of `%D'",
+ decl);
}
}
}
if (inlinep)
cp_error ("`%D' declared as an `inline' %s", object, type);
if (quals)
- cp_error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration", object, type);
+ cp_error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration",
+ object, type);
if (friendp)
cp_error_at ("invalid friend declaration", object);
if (raises)
CHECK is 1 if we must find this method in CTYPE, 0 if we should
not look, and -1 if we should not call `grokclassfn' at all. */
static tree
-grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, check, publicp)
+grokfndecl (ctype, type, declarator, virtualp, flags, quals,
+ raises, check, publicp)
tree ctype, type;
tree declarator;
int virtualp;
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo)) || flag_all_virtual == 1)
+ if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo))
+ || flag_all_virtual == 1)
{
tmp = get_first_matching_virtual (base_binfo, decl,
flags == DTOR_FLAG);
path to its virtual baseclass. */
if (staticp)
{
- cp_error ("method `%D' may not be declared static", decl);
- cp_error_at ("(since `%D' declared virtual in base class.)", tmp);
+ cp_error ("method `%D' may not be declared static",
+ decl);
+ cp_error_at ("(since `%D' declared virtual in base class.)",
+ tmp);
break;
}
virtualp = 1;
u = make_lang_type (UNION_TYPE);
fields[0] = build_lang_field_decl (FIELD_DECL, pfn_identifier, type);
- fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier, delta_type_node);
+ fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier,
+ delta_type_node);
finish_builtin_type (u, "__ptrmemfunc_type", fields, 1, ptr_type_node);
TYPE_NAME (u) = NULL_TREE;
/* Let the front-end know this is a pointer to member function. */
TYPE_PTRMEMFUNC_FLAG(t) = 1;
- fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, delta_type_node);
- fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier, delta_type_node);
+ fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
+ delta_type_node);
+ fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier,
+ delta_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, pfn_or_delta2_identifier, u);
finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node);
tree ctype = current_class_type;
tree ctor_return_type = NULL_TREE;
enum overload_flags flags = NO_SPECIAL;
- int seen_scope_ref = 0;
tree quals = NULL_TREE;
RIDBIT_RESET_ALL (specbits);
dname = decl;
decl = NULL_TREE;
- if (IDENTIFIER_TYPENAME_P (dname))
+ /* This may just be a variable starting with __op. */
+ if (IDENTIFIER_TYPENAME_P (dname) && TREE_TYPE (dname))
{
my_friendly_assert (flags == NO_SPECIAL, 154);
flags = TYPENAME_FLAG;
/* C++ extension */
case SCOPE_REF:
-/*
- if (seen_scope_ref == 1)
- error ("multiple `::' terms in declarator invalid");
-*/
- seen_scope_ref += 1;
{
/* Perform error checking, and convert class names to types.
We may call grokdeclarator multiple times for the same
}
else
{
- if (funcdef_flag && warn_return_type
- && return_type == return_normal
- && ! (RIDBIT_SETP (RID_SIGNED, specbits)
- || RIDBIT_SETP (RID_UNSIGNED, specbits)
- || RIDBIT_SETP (RID_LONG, specbits)
- || RIDBIT_SETP (RID_SHORT, specbits)))
- warn_about_return_type = 1;
- /* Save warning until we know what is really going on. */
+ if (funcdef_flag)
+ {
+ if (warn_return_type
+ && return_type == return_normal
+ && ! (RIDBIT_SETP (RID_SIGNED, specbits)
+ || RIDBIT_SETP (RID_UNSIGNED, specbits)
+ || RIDBIT_SETP (RID_LONG, specbits)
+ || RIDBIT_SETP (RID_SHORT, specbits)))
+ /* Save warning until we know what is really going on. */
+ warn_about_return_type = 1;
+ }
+ else if (class_binding_level && declarator
+ && TREE_CODE (declarator) == SCOPE_REF)
+ /* OK -- access declaration */;
+ else if (declspecs == NULL_TREE &&
+ (innermost_code != CALL_EXPR || pedantic))
+ cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type or storage class",
+ dname);
type = integer_type_node;
}
}
}
if (volatilep)
{
- error ("`volatile' specified for signature member function `%s'", name);
+ error ("`volatile' specified for signature member function `%s'",
+ name);
volatilep = 0;
}
if (inlinep)
}
if (virtualp)
{
- error ("`virtual' specified for signature member function `%s'", name);
+ error ("`virtual' specified for signature member function `%s'",
+ name);
/* Later, we'll make signature member functions virtual. */
virtualp = 0;
}
else
{
if (pedantic)
- cp_pedwarn ("ANSI C++ forbids variable-size array `%D'", dname);
+ cp_pedwarn ("ANSI C++ forbids variable-size array `%D'",
+ dname);
dont_grok_size:
itype =
build_binary_op (MINUS_EXPR, size, integer_one_node, 1);
/* don't fall out into global scope. Hides real bug? --eichin */ ;
else if (TREE_COMPLEXITY (declarator) == current_class_depth)
{
- /* I'm not really sure what pushclass calls this popclass
- corresponds to. One is in build_push_scope and that has
- been changed to a push_nested_class call, that's why I
- try to use pop_nested_class here instead.
- -niklas@appli.se */
+ /* This pop_nested_class corresponds to the
+ push_nested_class used to push into class scope for
+ parsing the argument list of a function decl, in
+ qualified_id. */
pop_nested_class (1);
TREE_COMPLEXITY (declarator) = current_class_depth;
}
}
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)
{
}
/* An operator with this name can be either unary or binary. */
-int ambi_op_p (name)
+static int
+ambi_op_p (name)
tree name;
{
return (name == ansi_opname [(int) INDIRECT_REF]
}
/* An operator with this name can only be unary. */
-int unary_op_p (name)
+static int
+unary_op_p (name)
tree name;
{
return (name == ansi_opname [(int) TRUTH_NOT_EXPR]
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
tree name = DECL_NAME (decl);
- tree t;
- if (! friendp)
- for (t = current_class_type; t; t = TYPE_NEXT_VARIANT (t))
- {
- if (name == ansi_opname[(int) MODIFY_EXPR])
- TYPE_HAS_ASSIGNMENT (t) = 1;
- else if (name == ansi_opname[(int) CALL_EXPR])
- TYPE_OVERLOADS_CALL_EXPR (t) = 1;
- else if (name == ansi_opname[(int) ARRAY_REF])
- TYPE_OVERLOADS_ARRAY_REF (t) = 1;
- else if (name == ansi_opname[(int) COMPONENT_REF]
- || name == ansi_opname[(int) MEMBER_REF])
- TYPE_OVERLOADS_ARROW (t) = 1;
- else if (name == ansi_opname[(int) NEW_EXPR])
- {
- if (TREE_CHAIN (argtypes) == void_list_node)
- TREE_GETS_NEW (t) = 1;
- else
- TREE_GETS_PLACED_NEW (t) = 1;
- }
- else if (name == ansi_opname[(int) DELETE_EXPR])
- TREE_GETS_DELETE (t) = 1;
-#if 0
- else if (name == ansi_opname[(int) VEC_NEW_EXPR])
- TREE_GETS_NEW (t) = 1;
- else if (name == ansi_opname[(int) VEC_DELETE_EXPR])
- TREE_GETS_DELETE (t) = 1;
-#endif
- }
+ if (current_class_type == NULL_TREE)
+ friendp = 1;
- if (name == ansi_opname[(int) NEW_EXPR])
+ if (! friendp)
+ {
+ if (name == ansi_opname[(int) MODIFY_EXPR])
+ TYPE_HAS_ASSIGNMENT (current_class_type) = 1;
+ else if (name == ansi_opname[(int) CALL_EXPR])
+ TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
+ else if (name == ansi_opname[(int) ARRAY_REF])
+ TYPE_OVERLOADS_ARRAY_REF (current_class_type) = 1;
+ else if (name == ansi_opname[(int) COMPONENT_REF]
+ || name == ansi_opname[(int) MEMBER_REF])
+ TYPE_OVERLOADS_ARROW (current_class_type) = 1;
+ else if (name == ansi_opname[(int) NEW_EXPR])
+ TYPE_GETS_NEW (current_class_type) |= 1;
+ else if (name == ansi_opname[(int) DELETE_EXPR])
+ TYPE_GETS_DELETE (current_class_type) |= 1;
+ else if (name == ansi_opname[(int) VEC_NEW_EXPR])
+ TYPE_GETS_NEW (current_class_type) |= 2;
+ else if (name == ansi_opname[(int) VEC_DELETE_EXPR])
+ TYPE_GETS_DELETE (current_class_type) |= 2;
+ }
+
+ if (name == ansi_opname[(int) NEW_EXPR]
+ || name == ansi_opname[(int) VEC_NEW_EXPR])
{
-#if 0
/* When the compiler encounters the definition of A::operator new, it
doesn't look at the class declaration to find out if it's static. */
- my_friendly_assert (!methodp, 355);
-#endif
+ if (methodp)
+ revert_static_member_fn (&TREE_TYPE (decl), &decl,
+ &TYPE_ARG_TYPES (TREE_TYPE (decl)));
/* Take care of function decl if we had syntax errors. */
if (argtypes == NULL_TREE)
hash_tree_chain (integer_type_node,
void_list_node));
else
- decl = coerce_new_type (TREE_TYPE (decl));
+ TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
}
-#if 0
- else if (name == ansi_opname[(int) VEC_NEW_EXPR])
- {
- }
-#endif
- else if (name == ansi_opname[(int) DELETE_EXPR])
+ else if (name == ansi_opname[(int) DELETE_EXPR]
+ || name == ansi_opname[(int) VEC_DELETE_EXPR])
{
-#if 0
- my_friendly_assert (!methodp, 355);
-#endif
+ if (methodp)
+ revert_static_member_fn (&TREE_TYPE (decl), &decl,
+ &TYPE_ARG_TYPES (TREE_TYPE (decl)));
if (argtypes == NULL_TREE)
TREE_TYPE (decl) =
hash_tree_chain (ptr_type_node,
void_list_node));
else
- decl = coerce_delete_type (TREE_TYPE (decl));
- }
-#if 0
- else if (name == ansi_opname[(int) VEC_DELETE_EXPR])
- {
+ {
+ TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
+
+ if (! friendp && name == ansi_opname[(int) VEC_DELETE_EXPR]
+ && (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)))
+ != void_list_node))
+ TYPE_VEC_DELETE_TAKES_SIZE (current_class_type) = 1;
+ }
}
-#endif
else
{
/* An operator function must either be a non-static member function
parmtype = TREE_VALUE (TREE_CHAIN (argtypes));
if (TREE_CODE (parmtype) == REFERENCE_TYPE
- && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype))
- == current_class_type)
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (parmtype))
+ == current_class_type)
+ && ! friendp)
{
TYPE_HAS_ASSIGN_REF (current_class_type) = 1;
if (TYPE_READONLY (TREE_TYPE (parmtype)))
}
TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype);
- TREE_GETS_NEW (ref) |= TREE_GETS_NEW (basetype);
- TREE_GETS_PLACED_NEW (ref) |= TREE_GETS_PLACED_NEW (basetype);
- TREE_GETS_DELETE (ref) |= TREE_GETS_DELETE (basetype);
+ TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
+ TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
i += 1;
}
/* If this doesn't return integer_type, complain. */
if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
{
- warning ("return type for `main' changed to integer type");
+ if (pedantic || warn_return_type)
+ warning ("return type for `main' changed to integer type");
TREE_TYPE (decl1) = fntype = default_function_type;
}
warn_about_return_type = 0;
/* These are two cases where we cannot delegate deletion. */
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)
- || TREE_GETS_DELETE (current_class_type))
+ || TYPE_GETS_REG_DELETE (current_class_type))
exprstmt = build_delete (current_class_type, C_C_D, integer_zero_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
else
virtual_size = c_sizeof (current_class_type);
/* At the end, call delete if that's what's requested. */
- if (TREE_GETS_DELETE (current_class_type))
+ if (TYPE_GETS_REG_DELETE (current_class_type))
/* This NOP_EXPR means we are in a static call context. */
exprstmt =
build_method_call
expand_decl_init (allocated_this);
/* How we cleanup `this' if an exception was raised before
we are ready to bail out. */
- cleanup = TREE_GETS_DELETE (current_class_type)
+ cleanup = TYPE_GETS_REG_DELETE (current_class_type)
? build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, allocated_this, virtual_size, NULL_TREE)
/* The size of allocated_this is wrong, and hence the
second argument to operator delete will be wrong. */
return error_mark_node;
}
+#if 0
/* If the type has no destructor, then we should build a regular
delete, instead of a vector delete. Otherwise, we would end
up passing a bogus offset into __builtin_delete, which is
doing_vec = 0;
use_global_delete = 1;
}
+#endif
if (doing_vec)
- return build_vec_delete (t, maxindex, elt_size, NULL_TREE,
- integer_one_node, integer_two_node);
+ return build_vec_delete (t, maxindex, elt_size, integer_one_node,
+ integer_two_node, use_global_delete);
else
return build_delete (type, t, integer_three_node,
LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE,
- use_global_delete
- || TYPE_HAS_DESTRUCTOR (TREE_TYPE (type)));
+ use_global_delete);
}
/* Sanity check: report error if this function FUNCTION is not
return value;
}
+#if 0
/* Like GROKFIELD, except that the declarator has been
buried in DECLSPECS. Find the declarator, and
return something that looks like it came from
DECL_IN_AGGR_P (decl) = 1;
return decl;
}
+#endif
tree
grokoptypename (declspecs, declarator)
else if (e3 |= e2)
{
if (arg_types == NULL_TREE)
- arg_types = void_list_node;
+ arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
else
arg_types = tree_cons (NULL_TREE, ptr_type_node, TREE_CHAIN (arg_types));
}
case BIT_NOT_EXPR:
return build_x_unary_op (BIT_NOT_EXPR,
reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)));
-
+ case SCOPE_REF:
+ return build_offset_ref (TREE_OPERAND (decl, 0), TREE_OPERAND (decl, 1));
+ case ARRAY_REF:
+ return grok_array_decl (reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)),
+ TREE_OPERAND (decl, 1));
default:
my_friendly_abort (5);
return NULL_TREE;
push_nested_class (TREE_OPERAND (decl, 0), 3);
TREE_COMPLEXITY (decl) = current_class_depth;
return decl;
+ case ARRAY_REF:
+ TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0));
+ return decl;
default:
my_friendly_abort (5);
return NULL_TREE;
declaration of a template type parameter named @code{T} or an unnamed
constant parameter of type @code{class T}. Section 14.6, paragraph 3 of
the January '94 working paper states that the first interpretation is
-the correct one. This ambiguity results in four reduce/reduce conflicts.
+the correct one. This ambiguity results in two reduce/reduce conflicts.
-2) Between @code{primary} and @code{typename} for code like @samp{int()}
+2) Between @code{primary} and @code{type_id} for code like @samp{int()}
in places where both can be accepted, such as the argument to
@code{sizeof}. Section 8.1 of the pre-San Diego working paper specifies
that these ambiguous constructs will be interpreted as @code{typename}s.
-This ambiguity results in six reduce/reduce conflicts.
+This ambiguity results in six reduce/reduce conflicts between
+@samp{absdcl} and @samp{functional_cast}.
-3) Between @code{primary}/@code{functional_cast} and
-@code{expr_or_declarator}/@code{complex_direct_notype_declarator}, for
-various token strings. This situation occurs in code looking like
+3) Between @code{functional_cast} and
+@code{complex_direct_notype_declarator}, for various token strings.
+This situation occurs in code looking like
@example
int (*a);
This code is ambiguous; it could be a declaration of the variable
@samp{a} as a pointer to @samp{int}, or it could be a functional cast of
@samp{*a} to @samp{int}. Section 6.8 specifies that the former
-interpretation is correct. This ambiguity results in 12 reduce/reduce
-conflicts. Ack.
-
-4) Between @code{after_type_declarator} and @code{parm}, for the token
-@code{TYPENAME}. This occurs in (as one example) code like
+interpretation is correct. This ambiguity results in 7 reduce/reduce
+conflicts. Another aspect of this ambiguity is code like 'int (x[2]);',
+which is resolved at the '[' and accounts for 6 reduce/reduce conflicts
+between @samp{direct_notype_declarator} and
+@samp{primary}/@samp{overqualified_id}. Finally, there are 4 r/r
+conflicts between @samp{expr_or_declarator} and @samp{primary} over code
+like 'int (a);', which could probably be resolved but would also
+probably be more trouble than it's worth. In all, this situation
+accounts for 17 conflicts. Ack!
+
+The second case above is responsible for the failure to parse 'LinppFile
+ppfile (String (argv[1]), &outs, argc, argv);' (from Rogue Wave
+Math.h++) as an object declaration, and must be fixed so that it does
+not resolve until later.
+
+4) Indirectly between @code{after_type_declarator} and @code{parm}, for
+type names. This occurs in (as one example) code like
@example
typedef int foo, bar;
What is @code{bar} inside the class definition? We currently interpret
it as a @code{parm}, as does Cfront, but IBM xlC interprets it as an
-@code{after_type_declarator}. I suspect that xlC is correct, in light
+@code{after_type_declarator}. I believe that xlC is correct, in light
of 7.1p2, which says "The longest sequence of @i{decl-specifiers} that
could possibly be a type name is taken as the @i{decl-specifier-seq} of
a @i{declaration}." However, it seems clear that this rule must be
-violated in the case of constructors, so...
+violated in the case of constructors. This ambiguity accounts for 8
+conflicts.
Unlike the others, this ambiguity is not recognized by the Working Paper.
static void expand_recursive_init ();
static void expand_virtual_init PROTO((tree, tree, tree));
tree expand_vec_init ();
-tree build_vec_delete ();
static void add_friend (), add_friends ();
/* Cache _builtin_new and _builtin_delete exprs. */
-static tree BIN, BID;
+static tree BIN, BID, BIVN, BIVD;
/* Cache the identifier nodes for the two magic field of a new cookie. */
static tree nc_nelts_field_id;
TREE_USED (TREE_OPERAND (BIN, 0)) = 0;
BID = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) DELETE_EXPR])));
TREE_USED (TREE_OPERAND (BID, 0)) = 0;
+ BIVN = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) VEC_NEW_EXPR])));
+ TREE_USED (TREE_OPERAND (BIVN, 0)) = 0;
+ BIVD = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) VEC_DELETE_EXPR])));
+ TREE_USED (TREE_OPERAND (BIVD, 0)) = 0;
minus_one = build_int_2 (-1, -1);
/* Define the structure that holds header information for
if (IDENTIFIER_HAS_TYPE_VALUE (name))
type = IDENTIFIER_TYPE_VALUE (name);
- else if (IDENTIFIER_HAS_CLASS_TYPE_VALUE (name))
- type = IDENTIFIER_CLASS_TYPE_VALUE (name);
else
{
if (or_else)
- cp_error ("`%T' fails to be an aggregate typedef", name);
+ cp_error ("`%T' is not an aggregate typedef", name);
return 0;
}
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM)
{
if (or_else)
- cp_error ("type `%T' is of non-aggregate type", type);
+ cp_error ("`%T' is not an aggregate type", type);
return 0;
}
return 1;
if (IDENTIFIER_HAS_TYPE_VALUE (name))
type = IDENTIFIER_TYPE_VALUE (name);
- else if (IDENTIFIER_HAS_CLASS_TYPE_VALUE (name))
- type = IDENTIFIER_CLASS_TYPE_VALUE (name);
else
{
if (or_else)
if (IDENTIFIER_HAS_TYPE_VALUE (name))
return IDENTIFIER_TYPE_VALUE (name);
- else if (IDENTIFIER_CLASS_VALUE (name))
- return IDENTIFIER_CLASS_TYPE_VALUE (name);
else
return NULL_TREE;
}
TREE_PUBLIC (decl) = 1;
add_friend (current_class_type, decl);
DECL_FRIEND_P (decl) = 1;
- if (IDENTIFIER_POINTER (declarator)[0] == '_')
- {
- if (! strcmp (IDENTIFIER_POINTER (declarator)+10, "new"))
- TREE_GETS_NEW (current_class_type) = 0;
- else if (! strcmp (IDENTIFIER_POINTER (declarator)+10, "delete"))
- TREE_GETS_DELETE (current_class_type) = 0;
- }
decl = void_type_node;
}
/* A global friend.
tree type, true_type, size, rval;
tree nelts;
int has_array = 0;
+ enum tree_code code = NEW_EXPR;
tree pending_sizes = NULL_TREE;
/* Get a little extra space to store a couple of things before the new'ed
array. */
- if (has_array && TYPE_NEEDS_DESTRUCTOR (true_type))
+ if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type))
{
tree extra = BI_header_size;
size = size_binop (PLUS_EXPR, size, extra);
}
+ if (has_array)
+ code = VEC_NEW_EXPR;
+
/* Allocate the object. */
- if (TYPE_LANG_SPECIFIC (true_type)
- && (TREE_GETS_NEW (true_type) || TREE_GETS_PLACED_NEW (true_type))
- && !use_global_new
- && !has_array)
- rval = build_opfncall (NEW_EXPR, LOOKUP_NORMAL,
+ if (! use_global_new && TYPE_LANG_SPECIFIC (true_type)
+ && (TYPE_GETS_NEW (true_type) & (1 << has_array)))
+ rval = build_opfncall (code, LOOKUP_NORMAL,
TYPE_POINTER_TO (true_type), size, placement);
else if (placement)
{
- rval = build_opfncall (NEW_EXPR, LOOKUP_GLOBAL|LOOKUP_COMPLAIN,
+ rval = build_opfncall (code, LOOKUP_GLOBAL|LOOKUP_COMPLAIN,
ptr_type_node, size, placement);
rval = convert (TYPE_POINTER_TO (true_type), rval);
}
- else if (flag_this_is_variable > 0
+ else if (! has_array && flag_this_is_variable > 0
&& TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node)
{
if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)
else
{
rval = build_builtin_call (build_pointer_type (true_type),
- BIN, build_tree_list (NULL_TREE, size));
+ has_array ? BIVN : BIN,
+ build_tree_list (NULL_TREE, size));
#if 0
/* See comment above as to why this is disabled. */
if (alignment)
}
#endif
TREE_CALLS_NEW (rval) = 1;
- TREE_SIDE_EFFECTS (rval) = 1;
}
/* if rval is NULL_TREE I don't have to allocate it, but are we totally
sure we have some extra bytes in that case for the BI_header_size
cookies? And how does that interact with the code below? (mrs) */
/* Finish up some magic for new'ed arrays */
- if (has_array && TYPE_NEEDS_DESTRUCTOR (true_type) && rval != NULL_TREE)
+ if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type) && rval != NULL_TREE)
{
tree extra = BI_header_size;
tree cookie, exp1;
This does not call any destructors. */
tree
-build_x_delete (type, addr, use_global_delete, virtual_size)
+build_x_delete (type, addr, which_delete, virtual_size)
tree type, addr;
- int use_global_delete;
+ int which_delete;
tree virtual_size;
{
+ int use_global_delete = which_delete & 1;
+ int use_vec_delete = !!(which_delete & 2);
tree rval;
+ enum tree_code code = use_vec_delete ? VEC_DELETE_EXPR : DELETE_EXPR;
- if (!use_global_delete
- && TYPE_LANG_SPECIFIC (TREE_TYPE (type))
- && TREE_GETS_DELETE (TREE_TYPE (type)))
- rval = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr,
- virtual_size, NULL_TREE);
+ if (! use_global_delete && TYPE_LANG_SPECIFIC (TREE_TYPE (type))
+ && (TYPE_GETS_DELETE (TREE_TYPE (type)) & (1 << use_vec_delete)))
+ rval = build_opfncall (code, LOOKUP_NORMAL, addr, virtual_size, NULL_TREE);
else
- rval = build_builtin_call (void_type_node, BID,
+ rval = build_builtin_call (void_type_node, use_vec_delete ? BIVD : BID,
build_tree_list (NULL_TREE, addr));
return rval;
}
addr = save_expr (addr);
return build_vec_delete (addr, array_type_nelts (type),
c_sizeof_nowarn (TREE_TYPE (type)),
- NULL_TREE, auto_delete, integer_two_node);
+ auto_delete, integer_two_node,
+ use_global_delete);
}
else
{
/* Pass the size of the object down to the operator delete() in
addition to the ADDR. */
- if (TREE_GETS_DELETE (type) && !use_global_delete)
+ if (TYPE_GETS_REG_DELETE (type) && !use_global_delete)
{
- /* This is probably wrong. It should be the size of the virtual
- object being deleted. */
tree virtual_size = c_sizeof_nowarn (type);
return build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr,
virtual_size, NULL_TREE);
operator delete, call the parent parent destructor (if any),
but let this node do the deleting. Otherwise, it is ok
to let the parent destructor do the deleting. */
- if (TREE_GETS_DELETE (type) && !use_global_delete)
+ if (TYPE_GETS_REG_DELETE (type) && !use_global_delete)
{
parent_auto_delete = integer_zero_node;
if (auto_delete == integer_zero_node)
MAXINDEX is the number of elements to be deleted.
ELT_SIZE is the nominal size of each element in the vector.
BASE is the expression that should yield the store to be deleted.
- DTOR_DUMMY is a placeholder for a destructor. The library function
- __builtin_vec_delete has a pointer to function in this position.
This function expands (or synthesizes) these calls itself.
AUTO_DELETE_VEC says whether the container (vector) should be deallocated.
AUTO_DELETE say whether each item in the container should be deallocated.
confirm the size, and trap if the numbers differ; not clear that it'd
be worth bothering.) */
tree
-build_vec_delete (base, maxindex, elt_size, dtor_dummy, auto_delete_vec, auto_delete)
+build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
+ use_global_delete)
tree base, maxindex, elt_size;
- tree dtor_dummy;
tree auto_delete_vec, auto_delete;
+ int use_global_delete;
{
tree ptype = TREE_TYPE (base);
tree type;
/* This is the real size */
virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
body = build_tree_list (NULL_TREE,
- build_x_delete (ptr_type_node, base_tbd, 1,
+ build_x_delete (ptype, base_tbd,
+ 2 | use_global_delete,
virtual_size));
body = build (COND_EXPR, void_type_node,
build (BIT_AND_EXPR, integer_type_node,
/* The below is short by BI_header_size */
virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex));
- if (loop == integer_zero_node)
+ if (! TYPE_VEC_NEW_USES_COOKIE (type))
/* no header */
base_tbd = base;
else
/* True size with header. */
virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
}
- deallocate_expr = build_x_delete (ptr_type_node, base_tbd, 1,
+ deallocate_expr = build_x_delete (ptype, base_tbd,
+ 2 | use_global_delete,
virtual_size);
if (auto_delete_vec != integer_one_node)
deallocate_expr = build (COND_EXPR, void_type_node,
IDENTIFIER_OPNAME_P (ansi_opname[(int) NEW_EXPR]) = 1;
ansi_opname[(int) DELETE_EXPR] = get_identifier ("__dl");
IDENTIFIER_OPNAME_P (ansi_opname[(int) DELETE_EXPR]) = 1;
+ ansi_opname[(int) VEC_NEW_EXPR] = get_identifier ("__vn");
+ IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_NEW_EXPR]) = 1;
+ ansi_opname[(int) VEC_DELETE_EXPR] = get_identifier ("__vd");
+ IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_DELETE_EXPR]) = 1;
ansi_opname[(int) TYPE_EXPR] = get_identifier ("__op");
IDENTIFIER_OPNAME_P (ansi_opname[(int) TYPE_EXPR]) = 1;
opname_tab[(int) MODIFY_EXPR] = "=";
opname_tab[(int) NEW_EXPR] = "new";
opname_tab[(int) DELETE_EXPR] = "delete";
+ opname_tab[(int) VEC_NEW_EXPR] = "new []";
+ opname_tab[(int) VEC_DELETE_EXPR] = "delete []";
opname_tab[(int) COND_EXPR] = "... ? ... : ...";
opname_tab[(int) CALL_EXPR] = "()";
opname_tab[(int) PLUS_EXPR] = "+";
case IDENTIFIER_DEFN:
case TYPENAME_DEFN:
case PTYPENAME_DEFN:
- case TYPENAME_COLON:
case TYPENAME_ELLIPSIS:
- case SCOPED_TYPENAME:
- case SCOPED_NAME:
case SCSPEC:
case PRE_PARSED_CLASS_DECL:
t = yylval.ttype;
register int c;
register int token;
- lineno++;
-
- /* Read first nonwhite char on the line. */
+ /* Read first nonwhite char on the line. Do this before incrementing the
+ line number, in case we're at the end of saved text. */
do
c = getch ();
while (c == ' ' || c == '\t');
+ lineno++;
+
if (c != '#')
{
/* If not #, return it so caller will use it. */
return c;
}
-/* Value is 1 if we should try to make the next identifier look like a
- typename (when it may be a local variable or a class variable).
- Value is 0 if we treat this name in a default fashion.
- Value is -1 if we must not see a type name. */
+/* Value is 1 (or 2) if we should try to make the next identifier look like
+ a typename (when it may be a local variable or a class variable).
+ Value is 0 if we treat this name in a default fashion. */
int looking_for_typename = 0;
+#if 0
+/* NO LONGER USED: Value is -1 if we must not see a type name. */
void
dont_see_typename ()
{
lastiddecl = 0;
}
}
+#endif
#ifdef __GNUC__
extern __inline int identifier_type ();
looking_for_typename = 0;
if (yychar == IDENTIFIER)
{
- lastiddecl = lookup_name (yylval.ttype, -1);
+ lastiddecl = lookup_name (yylval.ttype, -2);
if (lastiddecl == 0)
{
if (flag_labels_ok)
}
if (value == NEW && ! global_bindings_p ())
{
- looking_for_typename = 1;
value = NEW;
goto done;
}
/* Back-door communication channel to the lexer. */
extern int looking_for_typename;
+/* Tell the lexer where to look for names. */
+extern tree got_scope;
+
/* Pending language change.
Positive is push count, negative is pop count. */
extern int pending_lang_change;
{
char *name = IDENTIFIER_POINTER (dname);
- if (dname == ansi_opname[(int) NEW_EXPR]
- && parms != NULL_TREE
- && TREE_CODE (parms) == TREE_LIST
- && TREE_VALUE (parms) == sizetype
- && TREE_CHAIN (parms) == void_list_node)
- return get_identifier ("__builtin_new");
- else if (dname == ansi_opname[(int) DELETE_EXPR]
- && parms != NULL_TREE
- && TREE_CODE (parms) == TREE_LIST
- && TREE_VALUE (parms) == ptr_type_node
- && TREE_CHAIN (parms) == void_list_node)
- return get_identifier ("__builtin_delete");
- else if (dname == ansi_opname[(int) DELETE_EXPR]
- && parms != NULL_TREE
- && TREE_CODE (parms) == TREE_LIST
- && TREE_VALUE (parms) == ptr_type_node
- && TREE_CHAIN (parms) != NULL_TREE
- && TREE_CODE (TREE_CHAIN (parms)) == TREE_LIST
- && TREE_VALUE (TREE_CHAIN (parms)) == sizetype
- && TREE_CHAIN (TREE_CHAIN (parms)) == void_list_node)
- return get_identifier ("__builtin_delete");
+ /* member operators new and delete look like methods at this point. */
+ if (! for_method && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST)
+ {
+ if (TREE_VALUE (parms) == sizetype
+ && TREE_CHAIN (parms) == void_list_node)
+ {
+ if (dname == ansi_opname[(int) NEW_EXPR])
+ return get_identifier ("__builtin_new");
+ else if (dname == ansi_opname[(int) VEC_NEW_EXPR])
+ return get_identifier ("__builtin_vec_new");
+ }
+ else if (dname == ansi_opname[(int) DELETE_EXPR])
+ return get_identifier ("__builtin_delete");
+ else if (dname == ansi_opname[(int) VEC_DELETE_EXPR])
+ return get_identifier ("__builtin_vec_delete");
+ }
OB_INIT ();
if (for_method != 2)
try_second = 0;
break;
+ case VEC_NEW_EXPR:
case NEW_EXPR:
{
- fnname = ansi_opname[(int) NEW_EXPR];
+ tree args = tree_cons (NULL_TREE, xarg2, arg3);
+ fnname = ansi_opname[(int) code];
if (flags & LOOKUP_GLOBAL)
- return build_overload_call (fnname, tree_cons (NULL_TREE, xarg2, arg3),
- flags & LOOKUP_COMPLAIN,
+ return build_overload_call (fnname, args, flags & LOOKUP_COMPLAIN,
(struct candidate *)0);
rval = build_method_call
(build_indirect_ref (build1 (NOP_EXPR, xarg1, error_mark_node),
"new"),
- fnname, tree_cons (NULL_TREE, xarg2, arg3),
- NULL_TREE, flags);
+ fnname, args, NULL_TREE, flags);
if (rval == error_mark_node)
/* User might declare fancy operator new, but invoke it
like standard one. */
}
break;
+ case VEC_DELETE_EXPR:
case DELETE_EXPR:
{
- fnname = ansi_opname[(int) DELETE_EXPR];
+ fnname = ansi_opname[(int) code];
if (flags & LOOKUP_GLOBAL)
return build_overload_call (fnname,
- tree_cons (NULL_TREE, xarg1,
- build_tree_list (NULL_TREE, xarg2)),
+ build_tree_list (NULL_TREE, xarg1),
flags & LOOKUP_COMPLAIN,
(struct candidate *)0);
error_mark_node),
NULL_PTR),
fnname, tree_cons (NULL_TREE, xarg1,
- build_tree_list (NULL_TREE, xarg2)),
+ build_tree_list (NULL_TREE, xarg2)),
NULL_TREE, flags);
/* This happens when the user mis-declares `operator delete'.
Should now be impossible. */
#endif
extern int end_of_file;
+extern int current_class_depth;
void yyerror ();
/* Like YYERROR but do call yyerror. */
#define YYERROR1 { yyerror ("syntax error"); YYERROR; }
+#define OP0(NODE) (TREE_OPERAND (NODE, 0))
+#define OP1(NODE) (TREE_OPERAND (NODE, 1))
+
/* Contains the statement keyword (if/while/do) to include in an
error message if the user supplies an empty conditional expression. */
static char *cond_stmt_keyword;
but they can also serve as typespecs in declarations. */
%token TYPENAME
-/* Qualified identifiers that end in a TYPENAME. */
-%token SCOPED_TYPENAME
-
-/* Qualified identifiers that end in a IDENTIFIER. */
-%token SCOPED_NAME
-
/* Reserved words that specify storage class.
yylval contains an IDENTIFIER_NODE which indicates which one. */
%token SCSPEC
%token TYPEID DYNAMIC_CAST
%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.
The value is an integer because, if used, it is the tree code
to use in the expression made from the operator. */
%nonassoc IF
%nonassoc ELSE
-%left IDENTIFIER TYPENAME PTYPENAME TYPENAME_COLON SCSPEC TYPESPEC TYPE_QUAL ENUM AGGR ELLIPSIS SCOPED_TYPENAME TYPEOF SIGOF START_DECLARATOR OPERATOR
+%left IDENTIFIER TYPENAME PTYPENAME SCSPEC TYPESPEC TYPE_QUAL ENUM AGGR ELLIPSIS TYPEOF SIGOF OPERATOR
%left '{' ',' ';'
%type <ttype> compstmt except_stmts ansi_except_stmts implicitly_scoped_stmt
%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> structsp opt.component_decl_list component_decl_list
%type <ttype> component_decl components component_declarator
%type <ttype> notype_components notype_component_declarator
%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> type_id absdcl absdcl1 type_quals
+%type <ttype> type_id absdcl type_quals
%type <ttype> direct_abstract_declarator conversion_declarator
%type <ttype> new_type_id new_declarator direct_new_declarator
%type <ttype> xexpr parmlist parms parm bad_parm
%type <ttype> identifiers_or_typenames
%type <ttype> fcast_or_absdcl regcast_or_absdcl sub_cast_expr
-%type <ttype> expr_or_declarator complex_notype_declarator1
-%type <ttype> notype_unqualified_id
+%type <ttype> expr_or_declarator complex_notype_declarator
+%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> named_parm complex_parmlist typed_declspecs1 parms_comma
/* C++ extensions */
-%type <ttype> typename_scope
-%token <ttype> TYPENAME_COLON TYPENAME_ELLIPSIS
-%token <ttype> PTYPENAME SCOPED_TYPENAME SCOPED_NAME
+%token <ttype> TYPENAME_ELLIPSIS PTYPENAME
%token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL
%token <ttype> PRE_PARSED_CLASS_DECL
%type <ttype> fn.def1 /* Not really! */
%type <itype> base_class_access_list
%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> component_declarator0 id_scope scoped_typename scoped_base_class
-%type <ttype> forhead.1 identifier_or_opname operator_name
-%type <ttype> new delete object aggr
+%type <ttype> component_declarator0
+%type <ttype> forhead.1 operator_name
+%type <ttype> new object aggr
+%type <itype> delete
/* %type <ttype> primary_no_id */
%type <ttype> nonmomentary_expr
%type <itype> forhead.2 initdcl0 notype_initdcl0 member_init_list
%type <itype> .scope try ansi_try
%type <ttype> template_header template_parm_list template_parm
%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 <itype> fn_tmpl_end
/* %type <itype> try_for_typename */
%type <ttype> condition partially_scoped_stmt xcond paren_cond_or_null
%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. */
%token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN
warning ("restricted template type parameters not yet implemented");
$$ = build_tree_list ($2, $4);
}
- | aggr TYPENAME_COLON base_class.1
- {
- if ($1 == signature_type_node)
- sorry ("signature as template type parameter");
- else if ($1 != class_type_node)
- error ("template type parameter must use keyword `class'");
- warning ("restricted template type parameters not yet implemented");
- $$ = build_tree_list ($2, $3);
- }
| parm
;
;
datadef:
- notype_initdecls ';'
- { if (pedantic)
- pedwarn ("ANSI C++ forbids data definition with no type or storage class");
- else if (! flag_traditional && ! have_extern_spec)
- warning ("data definition has no type or storage class"); }
+ nomods_initdecls ';'
+ {}
| declmods notype_initdecls ';'
{}
/* Normal case to make fast: "const i;". */
YYERROR1;
reinit_parse_for_function ();
$$ = NULL_TREE; }
- | TYPENAME '(' parmlist ')' type_quals maybe_raises
- { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, $3, $5), $6, 0))
- YYERROR1;
- reinit_parse_for_function ();
- $$ = NULL_TREE; }
- | scoped_typename '(' parmlist ')' type_quals maybe_raises
- { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, $3, $5), $6, 0))
- YYERROR1;
- reinit_parse_for_function ();
- $$ = NULL_TREE; }
- | TYPENAME LEFT_RIGHT type_quals maybe_raises
- { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, empty_parms (), $3), $4, 0))
- YYERROR1;
- reinit_parse_for_function ();
- $$ = NULL_TREE; }
- | scoped_typename LEFT_RIGHT type_quals maybe_raises
- { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, empty_parms (), $3), $4, 0))
- YYERROR1;
- reinit_parse_for_function ();
- $$ = NULL_TREE; }
| PRE_PARSED_FUNCTION_DECL
{ start_function (NULL_TREE, TREE_VALUE ($$), NULL_TREE, 1);
reinit_parse_for_function (); }
fn.def2:
typed_declspecs '(' parmlist ')' type_quals maybe_raises
{
- tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), $3, $5);
- $$ = start_method (TREE_CHAIN ($$), decl, $6);
+ $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1), $3, $5);
+ $$ = start_method (TREE_CHAIN ($1), $$, $6);
+ rest_of_mdef:
if (! $$)
YYERROR1;
if (yychar == YYEMPTY)
reinit_parse_for_method (yychar, $$); }
| typed_declspecs LEFT_RIGHT type_quals maybe_raises
{
- tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), empty_parms (), $3);
- $$ = start_method (TREE_CHAIN ($$), decl, $4);
- if (! $$)
- YYERROR1;
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- reinit_parse_for_method (yychar, $$); }
+ $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1),
+ empty_parms (), $3);
+ $$ = start_method (TREE_CHAIN ($1), $$, $4);
+ goto rest_of_mdef;
+ }
| typed_declspecs declarator maybe_raises
- { $$ = start_method ($$, $2, $3);
- if (! $$)
- YYERROR1;
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- reinit_parse_for_method (yychar, $$); }
- | declmods '(' parmlist ')' type_quals maybe_raises
- {
- tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), $3, $5);
- $$ = start_method (TREE_CHAIN ($$), decl, $6);
- if (! $$)
- YYERROR1;
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- reinit_parse_for_method (yychar, $$); }
- | declmods LEFT_RIGHT type_quals maybe_raises
- {
- tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), empty_parms (), $3);
- $$ = start_method (TREE_CHAIN ($$), decl, $4);
- if (! $$)
- YYERROR1;
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- reinit_parse_for_method (yychar, $$); }
+ { $$ = start_method ($$, $2, $3); goto rest_of_mdef; }
| declmods notype_declarator maybe_raises
- { $$ = start_method ($$, $2, $3);
- if (! $$)
- YYERROR1;
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- reinit_parse_for_method (yychar, $$); }
+ { $$ = start_method ($$, $2, $3); goto rest_of_mdef; }
| notype_declarator maybe_raises
- { $$ = start_method (NULL_TREE, $$, $2);
- if (! $$)
- YYERROR1;
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- reinit_parse_for_method (yychar, $$); }
+ { $$ = start_method (NULL_TREE, $$, $2); goto rest_of_mdef; }
;
return_id: RETURN IDENTIFIER
pedwarn ("anachronistic old style base class initializer");
expand_member_init (C_C_D, NULL_TREE, void_type_node);
}
- | identifier '(' nonnull_exprlist ')'
- {
- expand_member_init (C_C_D, $<ttype>$, $3);
- }
- | identifier LEFT_RIGHT
- { expand_member_init (C_C_D, $<ttype>$, void_type_node); }
- | template_type_name '(' nonnull_exprlist ')'
+ | notype_identifier '(' nonnull_exprlist ')'
{ 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); }
- | scoped_typename '(' nonnull_exprlist ')'
+ | complete_type_name '(' nonnull_exprlist ')'
{ 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); }
- | 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);
}
;
| PTYPENAME
;
+notype_identifier:
+ IDENTIFIER
+ | PTYPENAME %prec EMPTY
+ ;
+
identifier_defn:
IDENTIFIER_DEFN
| TYPENAME_DEFN
| PTYPENAME_DEFN
;
-identifier_or_opname:
- IDENTIFIER
- | TYPENAME
- | PTYPENAME
-/* | '~' TYPENAME
- { $$ = build_parse_node (BIT_NOT_EXPR, $2); }*/
- /* get rid of the next line, replace it with the above */
- | '~' identifier { $$ = build_parse_node (BIT_NOT_EXPR,$2);}
- | operator_name
- ;
-
explicit_instantiation:
TEMPLATE aggr template_type
| TEMPLATE typed_declspecs declarator
;
template_type:
- template_type_name tmpl.1 template_instantiation
- {
- extern tree template_type_seen_before_scope;
-
- if ($3)
- $$ = $3;
- else if ($$ != error_mark_node)
- $$ = IDENTIFIER_TYPE_VALUE ($$);
- /* This is a kludge: In order to detect nested types inside
- * template classes, we have to tell the lexer that it should
- * try to replace a following SCOPE token with the correct
- * SCOPED_TYPENAME for the nested type. This SCOPED_TYPENAME
- * token will be handled in the rule "scoped_typename".
- * - niklas@appli.se */
- if (yychar == SCOPE)
- {
- /* We set template_type_seen_before_scope to be
- an error_mark_node so we can avoid meaningless
- and unhelpful syntax errors later. */
- if ($$ != error_mark_node)
- template_type_seen_before_scope = TYPE_IDENTIFIER ($$);
- else
- template_type_seen_before_scope = error_mark_node;
- yychar = YYLEX;
- }
- }
+ template_type_name tmpl.2 template_instantiation
+ { if ($3) $$ = $3; }
;
template_type_name:
{ $$ = lookup_template_class ($$, $3, NULL_TREE); }
;
-tmpl.1:
- /* Expansion of template may be required, unless we're followed by
- a class definition. */
- '{' { yyungetc ('{', 1); $$ = 0; }
- | ':' { yyungetc (':', 1); $$ = 0; }
- | /* empty */ %prec EMPTY
- { $$ = instantiate_class_template ($<ttype>0, 1); }
- ;
-
-tmpl.2:
+tmpl.2: %prec EMPTY
/* Always do expansion if it hasn't been done already. */
{ $$ = instantiate_class_template ($<ttype>0, 1); }
;
}
left_curly opt.component_decl_list '}'
{
- $$ = finish_struct ($<ttype>3, $5, 0);
+ tree t = finish_struct ($<ttype>3, $5, 0);
pop_obstacks ();
end_template_instantiation ($1);
pop_tinst_level();
- CLASSTYPE_GOT_SEMICOLON ($$) = 1;
+ CLASSTYPE_GOT_SEMICOLON (t) = 1;
}
;
| .scope new '(' nonnull_exprlist ')' '(' type_id ')'
{ $$ = build_new ($4, groktypename ($7), NULL_TREE,
$$ != NULL_TREE); }
- /* Unswallow a ':' which is probably meant for ?: expression. */
- | .scope new TYPENAME_COLON
- { yyungetc (':', 1); $$ = build_new ($2, $3, NULL_TREE, $$ != NULL_TREE); }
- | .scope new '(' nonnull_exprlist ')' TYPENAME_COLON
- { yyungetc (':', 1); $$ = build_new ($4, $6, NULL_TREE, $$ != NULL_TREE); }
| delete cast_expr %prec UNARY
- { $$ = delete_sanity ($2, NULL_TREE, 0, $$ != NULL_TREE); }
+ { $$ = delete_sanity ($2, NULL_TREE, 0, $1); }
| delete '[' ']' cast_expr %prec UNARY
- { $$ = delete_sanity ($4, NULL_TREE, 1, $$ != NULL_TREE);
+ { $$ = delete_sanity ($4, NULL_TREE, 1, $1);
if (yychar == YYEMPTY)
yychar = YYLEX; }
| delete '[' expr ']' cast_expr %prec UNARY
- { $$ = delete_sanity ($5, $3, 2, $$ != NULL_TREE);
+ { $$ = delete_sanity ($5, $3, 2, $1);
if (yychar == YYEMPTY)
yychar = YYLEX; }
;
;
notype_unqualified_id:
- '~' see_typename TYPENAME
- {
- destructor_name:
- $$ = build_parse_node (BIT_NOT_EXPR, $3);
- }
- | '~' see_typename IDENTIFIER
- { goto destructor_name; }
- | '~' see_typename PTYPENAME
- { goto destructor_name; }
+ '~' see_typename identifier
+ { $$ = build_parse_node (BIT_NOT_EXPR, $3); }
| operator_name
| IDENTIFIER
| PTYPENAME %prec EMPTY
;
+unqualified_id:
+ notype_unqualified_id
+ | TYPENAME
+ ;
+
expr_or_declarator:
- '*' expr_or_declarator %prec UNARY
+ notype_unqualified_id
+ | notype_qualified_id
+ | '*' expr_or_declarator %prec UNARY
{ $$ = build_parse_node (INDIRECT_REF, $2); }
| '&' expr_or_declarator %prec UNARY
{ $$ = build_parse_node (ADDR_EXPR, $2); }
- | notype_unqualified_id
- { see_typename (); }
;
direct_notype_declarator:
complex_direct_notype_declarator
| notype_unqualified_id
- { see_typename (); }
+ | notype_qualified_id
+ { push_nested_class (TREE_TYPE (OP0 ($$)), 3);
+ TREE_COMPLEXITY ($$) = current_class_depth; }
;
primary:
}
| primary '[' expr ']'
{ $$ = grok_array_decl ($$, $3); }
- | object identifier_or_opname %prec UNARY
- { $$ = build_component_ref ($$, $2, NULL_TREE, 1); }
- | object id_scope identifier_or_opname %prec UNARY
- { $$ = build_object_ref ($$, $2, $3); }
| primary PLUSPLUS
{ /* If we get an OFFSET_REF, turn it into what it really
means (e.g., a COMPONENT_REF). This way if we've got,
| TYPEID '(' type_id ')'
{ tree type = groktypename ($3);
$$ = get_typeid (type); }
- | SCOPE IDENTIFIER
+ | global_scope IDENTIFIER
{
do_scoped_id:
$$ = IDENTIFIER_GLOBAL_VALUE ($2);
}
}
- | SCOPE operator_name
+ | global_scope operator_name
{
+ got_scope = NULL_TREE;
if (TREE_CODE ($2) == IDENTIFIER_NODE)
goto do_scoped_id;
$$ = $2;
}
- | id_scope identifier_or_opname %prec HYPERUNARY
- { $$ = build_offset_ref ($$, $2); }
- | id_scope identifier_or_opname '(' nonnull_exprlist ')'
- { $$ = build_member_call ($$, $2, $4); }
- | id_scope identifier_or_opname LEFT_RIGHT
- { $$ = build_member_call ($$, $2, NULL_TREE); }
- | object identifier_or_opname '(' nonnull_exprlist ')'
+ | overqualified_id %prec HYPERUNARY
+ { $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
+ | overqualified_id '(' nonnull_exprlist ')'
+ { $$ = build_member_call (OP0 ($$), OP1 ($$), $3); }
+ | overqualified_id LEFT_RIGHT
+ { $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); }
+ | object unqualified_id %prec UNARY
+ { $$ = build_component_ref ($$, $2, NULL_TREE, 1); }
+ | object qualified_id %prec UNARY
+ { $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
+ | object unqualified_id '(' nonnull_exprlist ')'
{
#if 0
/* This is a future direction of this code, but because
(LOOKUP_NORMAL|LOOKUP_AGGR));
#endif
}
- | object identifier_or_opname LEFT_RIGHT
+ | object unqualified_id LEFT_RIGHT
{
#if 0
/* This is a future direction of this code, but because
(LOOKUP_NORMAL|LOOKUP_AGGR));
#endif
}
- | object id_scope identifier_or_opname '(' nonnull_exprlist ')'
+ | object qualified_id '(' nonnull_exprlist ')'
{
- if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE ($2)))
+ if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
{
warning ("signature name in scope resolution ignored");
- $$ = build_method_call ($$, $3, $5, NULL_TREE,
+ $$ = build_method_call ($$, OP1 ($2), $4, NULL_TREE,
(LOOKUP_NORMAL|LOOKUP_AGGR));
}
else
- $$ = build_scoped_method_call ($$, $2, $3, $5);
+ $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4);
}
- | object id_scope identifier_or_opname LEFT_RIGHT
+ | object qualified_id LEFT_RIGHT
{
- if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE ($2)))
+ if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
{
warning ("signature name in scope resolution ignored");
- $$ = build_method_call ($$, $3, NULL_TREE, NULL_TREE,
+ $$ = build_method_call ($$, OP1 ($2), NULL_TREE, NULL_TREE,
(LOOKUP_NORMAL|LOOKUP_AGGR));
}
else
- $$ = build_scoped_method_call ($$, $2, $3, NULL_TREE);
+ $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), NULL_TREE);
}
/* p->int::~int() is valid -- 12.4 */
| object '~' TYPESPEC LEFT_RIGHT
.scope:
/* empty */
{ $$ = 0; }
- | SCOPE
- { $$ = 1; }
+ | global_scope
+ { got_scope = NULL_TREE; $$ = 1; }
;
delete: DELETE
- { $$ = NULL_TREE; }
- | SCOPE delete
- { if ($2)
- error ("extra `::' before `delete' ignored");
- $$ = error_mark_node;
- }
+ { $$ = 0; }
+ | global_scope delete
+ { got_scope = NULL_TREE; $$ = 1; }
;
/* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */
;
decl:
- typed_declspecs initdecls ';'
- {
- resume_momentary ($2);
- note_list_got_semicolon ($1);
- }
- | typespec initdecls ';'
- {
- resume_momentary ($2);
+ /* Normal case: make this fast. */
+ typespec declarator ';'
+ { tree d = get_decl_list ($1);
+ int yes = suspend_momentary ();
+ d = start_decl ($2, d, 0, NULL_TREE);
+ finish_decl (d, NULL_TREE, NULL_TREE, 0);
+ resume_momentary (yes);
if (IS_AGGR_TYPE_CODE (TREE_CODE ($1)))
note_got_semicolon ($1);
}
- /* Normal case: make this fast. */
| typed_declspecs declarator ';'
{ tree d = $1;
int yes = suspend_momentary ();
resume_momentary (yes);
note_list_got_semicolon ($1);
}
- | typespec declarator ';'
- { tree d = get_decl_list ($1);
- int yes = suspend_momentary ();
- d = start_decl ($2, d, 0, NULL_TREE);
- finish_decl (d, NULL_TREE, NULL_TREE, 0);
- resume_momentary (yes);
+ | typespec initdecls ';'
+ {
+ resume_momentary ($2);
if (IS_AGGR_TYPE_CODE (TREE_CODE ($1)))
note_got_semicolon ($1);
}
- | declmods notype_initdecls ';'
- { resume_momentary ((int) $<itype>2); }
- /* Normal case: make this fast. */
- | declmods notype_declarator ';'
- { 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);
+ | typed_declspecs initdecls ';'
+ {
+ resume_momentary ($2);
+ note_list_got_semicolon ($1);
}
+ | declmods notype_initdecls ';'
+ { resume_momentary ($2); }
| typed_declspecs ';'
{
- shadow_tag ($<ttype>$);
- note_list_got_semicolon ($<ttype>$);
+ shadow_tag ($1);
+ note_list_got_semicolon ($1);
}
| declmods ';'
{ warning ("empty declaration"); }
typespec: structsp
| TYPESPEC %prec EMPTY
- | TYPENAME %prec EMPTY
- | scoped_typename %prec EMPTY
- | SCOPE TYPENAME %prec EMPTY
- { $$ = IDENTIFIER_GLOBAL_VALUE ($2);
- if (!$$)
- {
- error ("undeclared variable `%s' (first use here)",
- IDENTIFIER_POINTER ($2));
- $$ = error_mark_node;
- IDENTIFIER_GLOBAL_VALUE ($2) = error_mark_node;
- }
- else
- {
- $$ = TREE_TYPE($$);
- }
- }
+ | complete_type_name
| TYPEOF '(' expr ')'
{ $$ = TREE_TYPE ($3);
if (pedantic)
$$ = error_mark_node;
}
}
- | template_type %prec EMPTY
;
/* A typespec that is a reserved word, or a type qualifier. */
| notype_initdecls ',' initdcl
;
+nomods_initdecls:
+ nomods_initdcl0
+ | nomods_initdecls ',' initdcl
+ ;
+
maybeasm:
/* empty */
{ $$ = NULL_TREE; }
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
so that the header files compile. */
maybe_attribute:
check_for_missing_semicolon ($$); }
| ENUM identifier
{ $$ = xref_tag (enum_type_node, $2, NULL_TREE, 0); }
+ | ENUM complex_type_name
+ { $$ = xref_tag (enum_type_node, $2, NULL_TREE, 0); }
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
| class_head left_curly opt.component_decl_list '}'
named_class_head_sans_basetype:
aggr identifier
- { aggr1: current_aggr = $$; $$ = $2; }
- | aggr template_type_name %prec EMPTY
{ current_aggr = $$; $$ = $2; }
- | aggr TYPENAME_COLON
- { yyungetc (':', 1); goto aggr1; }
+ | aggr complex_type_name
+ { current_aggr = $$; $$ = $2; }
+ | aggr template_type %prec EMPTY
+ { current_aggr = $$; $$ = $2; }
| aggr template_type_name '{'
{ yyungetc ('{', 1);
aggr2:
else
$$ = build_tree_list ((tree)access_default, $$);
}
- | scoped_base_class
- {
- goto do_base_class1;
- }
| base_class_access_list base_class.1
{
tree type;
else
$$ = build_tree_list ((tree) $$, $2);
}
- | base_class_access_list scoped_base_class
- {
- goto do_base_class2;
- }
;
-scoped_base_class:
- base_class.1 SCOPED_TYPENAME
- {
- /* Kludge!!! See rule "template_type" and the code
- * dealing with "template_type_seen_before_scope" in
- * yylex(). */
- $$ = $2;
- }
- ;
base_class.1:
- template_type_name tmpl.2 template_instantiation
- {
- extern tree template_type_seen_before_scope;
- tree id = $3 ? TYPE_IDENTIFIER ($3) : $1;
-
- /* Check the rule template_type to get this... */
- if (yychar == YYEMPTY)
- yychar = YYLEX;
- if (yychar == SCOPE) {
- template_type_seen_before_scope = id;
- yychar = YYLEX;
- }
- }
- | identifier
+ complete_type_name
| SIGOF '(' expr ')'
{
if (current_aggr == signature_type_node)
}
pushclass ($<ttype>0, 0);
TYPE_BEING_DEFINED ($<ttype>0) = 1;
+#if 0
t = TYPE_IDENTIFIER ($<ttype>0);
if (t && IDENTIFIER_TEMPLATE (t))
overload_template_name (t, 1);
+#endif
}
;
;
component_decl:
- /* Do not add a "typed_declspecs declarator ';'" rule here for
+ component_decl_1 ';'
+ | component_decl_1 '}'
+ { error ("missing ';' before right brace");
+ yyungetc ('}', 0); }
+ /* C++: handle constructors, destructors and inline functions */
+ /* note that INLINE is like a TYPESPEC */
+ | fn.def2 ':' /* base_init compstmt */
+ { $$ = finish_method ($$); }
+ | fn.def2 '{' /* nodecls compstmt */
+ { $$ = finish_method ($$); }
+ ;
+
+component_decl_1:
+ /* Do not add a "typed_declspecs declarator" rule here for
speed; we need to call grok_x_components for enums, so the
speedup would be insignificant. */
- typed_declspecs components ';'
+ typed_declspecs components
{
$$ = grok_x_components ($$, $2);
end_exception_decls ();
}
- /* These rules introduce a reduce/reduce conflict; in
- typedef int foo, bar;
- class A {
- foo (bar);
- };
- should "A::foo" be declared as a function or data member?
- In other words, is "bar" an after_type_declarator or a parmlist? */
- | typed_declspecs '(' parmlist ')' ';'
- { $$ = groktypefield ($$, $3); }
- | typed_declspecs '(' parmlist ')' '}'
- { error ("missing ';' before right brace");
- yyungetc ('}', 0);
- $$ = groktypefield ($$, $3); }
- | typed_declspecs LEFT_RIGHT ';'
- { $$ = groktypefield ($$, empty_parms ()); }
- | typed_declspecs LEFT_RIGHT '}'
- { error ("missing ';' before right brace");
- yyungetc ('}', 0);
- $$ = groktypefield ($$, empty_parms ()); }
- | declmods notype_components ';'
+ | declmods notype_components
{
$$ = grok_x_components ($$, $2);
end_exception_decls ();
}
- /* Normal case: make this fast. */
- | declmods notype_declarator ';'
- { $$ = grokfield ($<ttype>2, $<ttype>$,
- NULL_TREE, NULL_TREE, NULL_TREE); }
- | declmods notype_components '}'
- { error ("missing ';' before right brace");
- yyungetc ('}', 0);
- $$ = grok_x_components ($$, $2);
- end_exception_decls ();
- }
- | declmods '(' parmlist ')' ';'
- { $$ = groktypefield ($$, $3); }
- | declmods '(' parmlist ')' '}'
- { error ("missing ';' before right brace");
- yyungetc ('}', 0);
- $$ = groktypefield ($$, $3); }
- | declmods LEFT_RIGHT ';'
- { $$ = groktypefield ($$, empty_parms ()); }
- | declmods LEFT_RIGHT '}'
- { error ("missing ';' before right brace");
- yyungetc ('}', 0);
- $$ = groktypefield ($$, empty_parms ()); }
- | ':' expr_no_commas ';'
+ | notype_declarator maybe_raises maybeasm maybe_attribute
+ { $$ = grokfield ($$, NULL_TREE, $2, NULL_TREE, $3);
+ cplus_decl_attributes ($$, $4); }
+ | ':' expr_no_commas
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
- | ':' expr_no_commas '}'
- { error ("missing ';' before right brace");
- yyungetc ('}', 0);
- $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
| error
{ $$ = NULL_TREE; }
- /* C++: handle constructors, destructors and inline functions */
- /* note that INLINE is like a TYPESPEC */
- | fn.def2 ':' /* base_init compstmt */
- { $$ = finish_method ($$); }
- | fn.def2 '{' /* nodecls compstmt */
- { $$ = finish_method ($$); }
- | notype_declarator maybe_raises ';'
- { $$ = grokfield ($$, NULL_TREE, $2, NULL_TREE, NULL_TREE); }
- | notype_declarator maybe_raises '}'
- { error ("missing ';' before right brace");
- yyungetc ('}', 0);
- $$ = grokfield ($$, NULL_TREE, $2, NULL_TREE, NULL_TREE); }
+ /* These rules introduce a reduce/reduce conflict; in
+ typedef int foo, bar;
+ class A {
+ foo (bar);
+ };
+ should "A::foo" be declared as a function or "A::bar" as a data
+ member? In other words, is "bar" an after_type_declarator or a
+ parmlist? */
+ | typed_declspecs '(' parmlist ')' type_quals
+ { $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1),
+ $3, $5);
+ $$ = grokfield ($$, TREE_CHAIN ($1), NULL_TREE, NULL_TREE,
+ NULL_TREE); }
+ | typed_declspecs LEFT_RIGHT type_quals
+ { $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1),
+ empty_parms (), $3);
+ $$ = grokfield ($$, TREE_CHAIN ($1), NULL_TREE, NULL_TREE,
+ NULL_TREE); }
;
/* The case of exactly one component is handled directly by component_decl. */
{ $$ = build_decl_list ($$, NULL_TREE); }
;
-/* ANSI abstract-declarator (8.1) */
-absdcl:
- absdcl1 %prec EMPTY
- | START_DECLARATOR absdcl1 %prec EMPTY
- { $$ = $2; }
- ;
-
type_quals:
/* empty */ %prec EMPTY
{ $$ = NULL_TREE; }
/* A declarator that is allowed only after an explicit typespec. */
/* may all be followed by prec '.' */
after_type_declarator:
- after_type_declarator1
- | START_DECLARATOR after_type_declarator1
- { $$ = $2; }
- ;
-
-after_type_declarator1:
- '*' nonempty_type_quals after_type_declarator1 %prec UNARY
+ '*' nonempty_type_quals after_type_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
- | '&' nonempty_type_quals after_type_declarator1 %prec UNARY
+ | '&' nonempty_type_quals after_type_declarator %prec UNARY
{ $$ = make_reference_declarator ($2, $3); }
- | '*' after_type_declarator1 %prec UNARY
+ | '*' after_type_declarator %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
- | '&' after_type_declarator1 %prec UNARY
+ | '&' after_type_declarator %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | id_scope '*' type_quals after_type_declarator1
- { tree arg = make_pointer_declarator ($3, $4);
- if (TREE_CODE ($$) != SCOPE_REF)
- $$ = build_push_scope ($$, arg);
- else if (TREE_OPERAND ($$, 1) == NULL_TREE)
- TREE_OPERAND ($$, 1) = arg;
- else
- $$ = build_parse_node (SCOPE_REF, $$, arg);
+ | ptr_to_mem type_quals after_type_declarator
+ { tree arg = make_pointer_declarator ($2, $3);
+ $$ = build_parse_node (SCOPE_REF, $1, arg);
}
| direct_after_type_declarator
;
+qualified_type_name:
+ type_name %prec EMPTY
+ | nested_type
+ ;
+
+nested_type:
+ nested_name_specifier type_name %prec EMPTY
+ { $$ = $2; }
+ ;
+
direct_after_type_declarator:
direct_after_type_declarator '(' nonnull_exprlist ')' type_quals %prec '.'
{ $$ = build_parse_node (CALL_EXPR, $$, $3, $5); }
{ $$ = build_parse_node (ARRAY_REF, $$, $3); }
| direct_after_type_declarator '[' ']'
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
- | '(' after_type_declarator1 ')'
+ | '(' after_type_declarator ')'
{ $$ = $2; }
- | TYPENAME %prec EMPTY
+ | nested_name_specifier type_name %prec EMPTY
+ { push_nested_class (TREE_TYPE ($$), 3);
+ $$ = build_parse_node (SCOPE_REF, $$, $2);
+ TREE_COMPLEXITY ($$) = current_class_depth; }
+ | type_name %prec EMPTY
;
/* A declarator allowed whether or not there has been
an explicit typespec. These cannot redeclare a typedef-name. */
notype_declarator:
- notype_declarator1
- | START_DECLARATOR notype_declarator1
- { $$ = $2; }
- ;
-
-notype_declarator1:
- '*' nonempty_type_quals notype_declarator1 %prec UNARY
+ '*' nonempty_type_quals notype_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
- | '&' nonempty_type_quals notype_declarator1 %prec UNARY
+ | '&' nonempty_type_quals notype_declarator %prec UNARY
{ $$ = make_reference_declarator ($2, $3); }
- | '*' notype_declarator1 %prec UNARY
+ | '*' notype_declarator %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
- | '&' notype_declarator1 %prec UNARY
+ | '&' notype_declarator %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | id_scope '*' type_quals notype_declarator1
- { tree arg = make_pointer_declarator ($3, $4);
- if (TREE_CODE ($$) != SCOPE_REF)
- $$ = build_push_scope ($$, arg);
- else if (TREE_OPERAND ($$, 1) == NULL_TREE)
- TREE_OPERAND ($$, 1) = arg;
- else
- $$ = build_parse_node (SCOPE_REF, $$, arg);
+ | ptr_to_mem type_quals notype_declarator
+ { tree arg = make_pointer_declarator ($2, $3);
+ $$ = build_parse_node (SCOPE_REF, $1, arg);
}
| direct_notype_declarator
;
-complex_notype_declarator1:
- '*' nonempty_type_quals notype_declarator1 %prec UNARY
+complex_notype_declarator:
+ '*' nonempty_type_quals notype_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
- | '&' nonempty_type_quals notype_declarator1 %prec UNARY
+ | '&' nonempty_type_quals notype_declarator %prec UNARY
{ $$ = make_reference_declarator ($2, $3); }
- | '*' complex_notype_declarator1 %prec UNARY
+ | '*' complex_notype_declarator %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
- | '&' complex_notype_declarator1 %prec UNARY
+ | '&' complex_notype_declarator %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | id_scope '*' type_quals notype_declarator1
- { tree arg = make_pointer_declarator ($3, $4);
- if (TREE_CODE ($$) != SCOPE_REF)
- $$ = build_push_scope ($$, arg);
- else if (TREE_OPERAND ($$, 1) == NULL_TREE)
- TREE_OPERAND ($$, 1) = arg;
- else
- $$ = build_parse_node (SCOPE_REF, $$, arg);
+ | ptr_to_mem type_quals notype_declarator
+ { tree arg = make_pointer_declarator ($2, $3);
+ $$ = build_parse_node (SCOPE_REF, $1, arg);
}
| complex_direct_notype_declarator
;
{ $$ = build_parse_node (CALL_EXPR, $$, NULL_TREE, NULL_TREE); }
| '(' expr_or_declarator ')'
{ $$ = finish_decl_parsing ($2); }
- | '(' complex_notype_declarator1 ')'
+ | '(' complex_notype_declarator ')'
{ $$ = $2; }
| direct_notype_declarator '[' nonmomentary_expr ']'
{ $$ = build_parse_node (ARRAY_REF, $$, $3); }
| direct_notype_declarator '[' ']'
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
+ ;
- /* C++ extensions. */
- | id_scope see_typename notype_unqualified_id
- { see_typename ();
- if (TREE_CODE ($$) != SCOPE_REF)
- $$ = build_push_scope ($$, $3);
- else if (TREE_OPERAND ($$, 1) == NULL_TREE)
- TREE_OPERAND ($$, 1) = $3;
- else
- $$ = build_parse_node (SCOPE_REF, $$, $3);
- }
- | id_scope see_typename TYPENAME
- { $$ = build_push_scope ($$, $3); }
- | SCOPE see_typename direct_notype_declarator
- { $$ = build_parse_node (SCOPE_REF, NULL_TREE, $3); }
- | template_type SCOPED_NAME
- { tree t;
- extern int current_class_depth;
+qualified_id:
+ nested_name_specifier unqualified_id
+ { got_scope = NULL_TREE;
+ $$ = build_parse_node (SCOPE_REF, $$, $2); }
+ ;
- t = TREE_TYPE(TREE_OPERAND($2, 0));
- if (t != current_class_type &&
- TREE_CODE(t) != TEMPLATE_TYPE_PARM)
- {
- push_nested_class(t, 3);
- TREE_COMPLEXITY ($2) = current_class_depth;
- }
- $$ = $2;
- }
+notype_qualified_id:
+ nested_name_specifier notype_unqualified_id
+ { got_scope = NULL_TREE;
+ $$ = build_parse_node (SCOPE_REF, $$, $2); }
+ ;
+
+overqualified_id:
+ notype_qualified_id
+ | global_scope notype_qualified_id
+ { $$ = $2; }
;
functional_cast:
{ $$ = reparse_absdcl_as_expr ($$, $2); }
;
-id_scope: typename_scope
- { tree t;
- do_id_scope:
+type_name:
+ TYPENAME
+ | template_type %prec EMPTY
+ ;
- t = resolve_scope_to_name (NULL_TREE, $$);
- if (t == NULL_TREE)
- {
- cp_error ("`%T' is not a valid scope", $$);
- $$ = error_mark_node;
- }
- else
- $$ = t;
- }
+nested_name_specifier:
+ nested_name_specifier_1
+ | nested_name_specifier nested_name_specifier_1
+ { $$ = $2; }
+ ;
+
+/* Why the @#$%^& do type_name and notype_identifier need to be expanded
+ inline here?!? (jason) */
+nested_name_specifier_1:
+ TYPENAME SCOPE
+ { got_scope = TREE_TYPE ($$); }
+ | template_type SCOPE
+ { got_scope = TREE_TYPE ($$); }
+/* These break 'const i;'
| IDENTIFIER SCOPE
- { goto do_id_scope; }
- | template_type SCOPE /* try_for_typename %prec EMPTY */
{
- if ($$ == error_mark_node)
- /* leave it alone */;
- else
- {
- $$ = resolve_scope_to_name (NULL_TREE, TYPE_IDENTIFIER ($$));
- if ($$ == NULL_TREE)
- {
- error ("undefined explicitly scoped type");
- $$ = error_mark_node;
- }
- }
-/* if ($3) popclass (1); */
+ failed_scope:
+ cp_error ("`%D' is not an aggregate typedef",
+ lastiddecl ? lastiddecl : $$);
+ $$ = error_mark_node;
}
+ | PTYPENAME SCOPE
+ { goto failed_scope; } */
;
-typename_scope:
- TYPENAME SCOPE;
+complete_type_name:
+ qualified_type_name
+ | global_scope qualified_type_name
+ { $$ = $2; }
+ ;
-scoped_typename: SCOPED_TYPENAME
- | template_type SCOPED_TYPENAME
- {
- /* Kludge!!! See rule "template_type" and the code
- * dealing with "template_type_seen_before_scope" in
- * yylex(). */
- $$ = $2;
- }
-/* | template_type SCOPE try_for_typename TYPENAME
- {
- if ($$ == error_mark_node)
- ;
- else
- {
- $$ = build_parse_node (SCOPE_REF,
- TYPE_IDENTIFIER ($$),
- $4);
- }
- if ($3) popclass (1);
- } */
+complex_type_name:
+ nested_type
+ | global_scope qualified_type_name
+ { $$ = $2; }
+ ;
+
+ptr_to_mem:
+ nested_name_specifier '*'
+ { got_scope = NULL_TREE; }
+ | global_scope nested_name_specifier '*'
+ { $$ = $2; got_scope = NULL_TREE; }
+ ;
+
+/* All uses of explicit global scope must go through this nonterminal so
+ that got_scope will be set before yylex is called to get the next token. */
+global_scope:
+ SCOPE
+ { got_scope = void_type_node; }
;
/* ANSI new-declarator (5.3.4) */
{ $$ = make_reference_declarator ($2, $3); }
| '&' type_quals %prec EMPTY
{ $$ = make_reference_declarator ($2, NULL_TREE); }
- | id_scope '*' type_quals %prec EMPTY
- { tree arg = make_pointer_declarator ($3, NULL_TREE);
- if (TREE_CODE ($$) != SCOPE_REF)
- $$ = build_push_scope ($$, arg);
- else if (TREE_OPERAND ($$, 1) == NULL_TREE)
- TREE_OPERAND ($$, 1) = arg;
- else
- $$ = build_parse_node (SCOPE_REF, $$, arg);
+ | ptr_to_mem type_quals %prec EMPTY
+ { tree arg = make_pointer_declarator ($2, NULL_TREE);
+ $$ = build_parse_node (SCOPE_REF, $1, arg);
}
- | id_scope '*' type_quals new_declarator
- { tree arg = make_pointer_declarator ($3, $4);
- if (TREE_CODE ($$) != SCOPE_REF)
- $$ = build_push_scope ($$, arg);
- else if (TREE_OPERAND ($$, 1) == NULL_TREE)
- TREE_OPERAND ($$, 1) = arg;
- else
- $$ = build_parse_node (SCOPE_REF, $$, arg);
+ | ptr_to_mem type_quals new_declarator
+ { tree arg = make_pointer_declarator ($2, $3);
+ $$ = build_parse_node (SCOPE_REF, $1, arg);
}
| direct_new_declarator %prec EMPTY
;
;
/* ANSI abstract-declarator (8.1) */
-absdcl1:
- '*' nonempty_type_quals absdcl1
+absdcl:
+ '*' nonempty_type_quals absdcl
{ $$ = make_pointer_declarator ($2, $3); }
- | '*' absdcl1
+ | '*' absdcl
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
| '*' type_quals %prec EMPTY
{ $$ = make_pointer_declarator ($2, NULL_TREE); }
- | '&' nonempty_type_quals absdcl1
+ | '&' nonempty_type_quals absdcl
{ $$ = make_reference_declarator ($2, $3); }
- | '&' absdcl1
+ | '&' absdcl
{ $$ = make_reference_declarator (NULL_TREE, $2); }
| '&' type_quals %prec EMPTY
{ $$ = make_reference_declarator ($2, NULL_TREE); }
- | id_scope '*' type_quals %prec EMPTY
- { tree arg = make_pointer_declarator ($3, NULL_TREE);
- if (TREE_CODE ($$) != SCOPE_REF)
- $$ = build_push_scope ($$, arg);
- else if (TREE_OPERAND ($$, 1) == NULL_TREE)
- TREE_OPERAND ($$, 1) = arg;
- else
- $$ = build_parse_node (SCOPE_REF, $$, arg);
+ | ptr_to_mem type_quals %prec EMPTY
+ { tree arg = make_pointer_declarator ($2, NULL_TREE);
+ $$ = build_parse_node (SCOPE_REF, $1, arg);
}
- | id_scope '*' type_quals absdcl1
- { tree arg = make_pointer_declarator ($3, $4);
- if (TREE_CODE ($$) != SCOPE_REF)
- $$ = build_push_scope ($$, arg);
- else if (TREE_OPERAND ($$, 1) == NULL_TREE)
- TREE_OPERAND ($$, 1) = arg;
- else
- $$ = build_parse_node (SCOPE_REF, $$, arg);
+ | ptr_to_mem type_quals absdcl
+ { tree arg = make_pointer_declarator ($2, $3);
+ $$ = build_parse_node (SCOPE_REF, $1, arg);
}
| direct_abstract_declarator %prec EMPTY
;
/* ANSI direct-abstract-declarator (8.1) */
direct_abstract_declarator:
- '(' absdcl1 ')'
- { see_typename ();
- $$ = $2; }
+ '(' absdcl ')'
+ { $$ = $2; }
/* `(typedef)1' is `int'. */
| PAREN_STAR_PAREN
- { see_typename (); }
| direct_abstract_declarator '(' parmlist ')' type_quals %prec '.'
{ $$ = build_parse_node (CALL_EXPR, $$, $3, $5); }
| direct_abstract_declarator LEFT_RIGHT type_quals %prec '.'
}
| PTYPENAME ':'
{ goto do_label; }
- | TYPENAME_COLON
- { tree label = define_label (input_filename, lineno, $1);
- if (label)
- expand_label (label);
- }
;
try_head: TRY '{' { cplus_expand_start_try (0); } .pushlevel
/* Here we expand typed_declspecs inline to avoid mis-parsing of
TYPESPEC IDENTIFIER. */
typed_declspecs1 declarator
- { $$ = build_tree_list ($$, $2);
- see_typename (); }
+ { $$ = build_tree_list ($$, $2); }
| typed_typespecs declarator
- { $$ = build_tree_list ($$, $2);
- see_typename (); }
+ { $$ = build_tree_list ($$, $2); }
| typespec declarator
- { $$ = build_tree_list (get_decl_list ($$), $2);
- see_typename (); }
+ { $$ = build_tree_list (get_decl_list ($$), $2); }
| typed_declspecs1 absdcl
- { $$ = build_tree_list ($$, $2);
- see_typename (); }
+ { $$ = build_tree_list ($$, $2); }
| typed_declspecs1 %prec EMPTY
- { $$ = build_tree_list ($$, NULL_TREE);
- see_typename (); }
+ { $$ = build_tree_list ($$, NULL_TREE); }
| declmods notype_declarator
- { $$ = build_tree_list ($$, $2);
- see_typename (); }
+ { $$ = build_tree_list ($$, $2); }
;
parm:
{ $$ = build_decl_list (NULL_TREE, $$); }
| TYPENAME
{ $$ = build_decl_list (NULL_TREE, $$); }
- | SCOPE IDENTIFIER
- { $$ = build_decl_list (void_type_node, $2); }
- | SCOPE TYPENAME
- { $$ = build_decl_list (void_type_node, $2); }
- | id_scope IDENTIFIER
- { $$ = build_decl_list ($$, $2); }
- | scoped_typename
+ | global_scope IDENTIFIER
+ { $$ = build_decl_list (NULL_TREE, $2); }
+ | global_scope TYPENAME
+ { $$ = build_decl_list (NULL_TREE, $2); }
;
ansi_raise_identifier:
{ $$ = make_pointer_declarator ($2, $3); }
| '&' type_quals conversion_declarator
{ $$ = make_reference_declarator ($2, $3); }
- | id_scope '*' type_quals conversion_declarator
- { tree arg = make_pointer_declarator ($3, $4);
- if (TREE_CODE ($$) != SCOPE_REF)
- $$ = build_push_scope ($$, arg);
- else if (TREE_OPERAND ($$, 1) == NULL_TREE)
- TREE_OPERAND ($$, 1) = arg;
- else
- $$ = build_parse_node (SCOPE_REF, $$, arg);
+ | ptr_to_mem type_quals conversion_declarator
+ { tree arg = make_pointer_declarator ($2, $3);
+ $$ = build_parse_node (SCOPE_REF, $1, arg);
}
;
+operator: OPERATOR
+ { got_scope = NULL_TREE; }
+ ;
+
operator_name:
- OPERATOR '*'
+ operator '*'
{ $$ = ansi_opname[MULT_EXPR]; }
- | OPERATOR '/'
+ | operator '/'
{ $$ = ansi_opname[TRUNC_DIV_EXPR]; }
- | OPERATOR '%'
+ | operator '%'
{ $$ = ansi_opname[TRUNC_MOD_EXPR]; }
- | OPERATOR '+'
+ | operator '+'
{ $$ = ansi_opname[PLUS_EXPR]; }
- | OPERATOR '-'
+ | operator '-'
{ $$ = ansi_opname[MINUS_EXPR]; }
- | OPERATOR '&'
+ | operator '&'
{ $$ = ansi_opname[BIT_AND_EXPR]; }
- | OPERATOR '|'
+ | operator '|'
{ $$ = ansi_opname[BIT_IOR_EXPR]; }
- | OPERATOR '^'
+ | operator '^'
{ $$ = ansi_opname[BIT_XOR_EXPR]; }
- | OPERATOR '~'
+ | operator '~'
{ $$ = ansi_opname[BIT_NOT_EXPR]; }
- | OPERATOR ','
+ | operator ','
{ $$ = ansi_opname[COMPOUND_EXPR]; }
- | OPERATOR ARITHCOMPARE
+ | operator ARITHCOMPARE
{ $$ = ansi_opname[$2]; }
- | OPERATOR '<'
+ | operator '<'
{ $$ = ansi_opname[LT_EXPR]; }
- | OPERATOR '>'
+ | operator '>'
{ $$ = ansi_opname[GT_EXPR]; }
- | OPERATOR EQCOMPARE
+ | operator EQCOMPARE
{ $$ = ansi_opname[$2]; }
- | OPERATOR ASSIGN
+ | operator ASSIGN
{ $$ = ansi_assopname[$2]; }
- | OPERATOR '='
+ | operator '='
{ $$ = ansi_opname [MODIFY_EXPR]; }
- | OPERATOR LSHIFT
+ | operator LSHIFT
{ $$ = ansi_opname[$2]; }
- | OPERATOR RSHIFT
+ | operator RSHIFT
{ $$ = ansi_opname[$2]; }
- | OPERATOR PLUSPLUS
+ | operator PLUSPLUS
{ $$ = ansi_opname[POSTINCREMENT_EXPR]; }
- | OPERATOR MINUSMINUS
+ | operator MINUSMINUS
{ $$ = ansi_opname[PREDECREMENT_EXPR]; }
- | OPERATOR ANDAND
+ | operator ANDAND
{ $$ = ansi_opname[TRUTH_ANDIF_EXPR]; }
- | OPERATOR OROR
+ | operator OROR
{ $$ = ansi_opname[TRUTH_ORIF_EXPR]; }
- | OPERATOR '!'
+ | operator '!'
{ $$ = ansi_opname[TRUTH_NOT_EXPR]; }
- | OPERATOR '?' ':'
+ | operator '?' ':'
{ $$ = ansi_opname[COND_EXPR]; }
- | OPERATOR MIN_MAX
+ | operator MIN_MAX
{ $$ = ansi_opname[$2]; }
- | OPERATOR POINTSAT %prec EMPTY
+ | operator POINTSAT %prec EMPTY
{ $$ = ansi_opname[COMPONENT_REF]; }
- | OPERATOR POINTSAT_STAR %prec EMPTY
+ | operator POINTSAT_STAR %prec EMPTY
{ $$ = ansi_opname[MEMBER_REF]; }
- | OPERATOR LEFT_RIGHT
+ | operator LEFT_RIGHT
{ $$ = ansi_opname[CALL_EXPR]; }
- | OPERATOR '[' ']'
+ | operator '[' ']'
{ $$ = ansi_opname[ARRAY_REF]; }
- | OPERATOR NEW
+ | operator NEW %prec EMPTY
{ $$ = ansi_opname[NEW_EXPR]; }
- | OPERATOR DELETE
+ | operator DELETE %prec EMPTY
{ $$ = ansi_opname[DELETE_EXPR]; }
-/* | OPERATOR NEW '[' ']'
+ | operator NEW '[' ']'
{ $$ = ansi_opname[VEC_NEW_EXPR]; }
- | OPERATOR DELETE '[' ']'
- { $$ = ansi_opname[VEC_DELETE_EXPR]; } */
- | OPERATOR typed_typespecs conversion_declarator
+ | operator DELETE '[' ']'
+ { $$ = ansi_opname[VEC_DELETE_EXPR]; }
+ /* Should we be pushing into class scope to parse this? */
+ | operator typed_typespecs conversion_declarator
{ $$ = grokoptypename ($2, $3); }
- | OPERATOR error
+ | operator error
{ $$ = ansi_opname[ERROR_MARK]; }
;
return fndecl;
}
+/* classlevel should now never be true. jason 4/12/94 */
void
undo_template_name_overload (id, classlevel)
tree id;
#endif
}
+/* classlevel should now never be true. jason 4/12/94 */
void
overload_template_name (id, classlevel)
tree id;
#if 1 /* XXX */
/* This was a botch... names of templates do not get their own private
- scopes. Rather, the names of generated template instances should
- just get pushed into whatever scope we happen to be in at the moment.
- This will typically (but not always) be the global scope. (Maybe
- what we really want to do here is a `push_to_toplevel' and then stay
- there while we are generating the instance; popping back out to the
- current scope when we are done generating the instance.) */
+ scopes. Rather, they should go into the binding level already created
+ by push_template_decls. Except that there isn't one of those for
+ specializations. */
if (!classlevel)
{
pushlevel (1);
if (classlevel)
pushdecl_class_level (decl);
else
-#if 0 /* not yet, should get fixed properly later */
pushdecl (decl);
- pushlevel (1);
-#else
- {
- pushdecl (decl);
- /* @@ Is this necessary now? */
- IDENTIFIER_LOCAL_VALUE (template) = decl;
- }
-#endif
+#if 0 /* This seems bogus to me; if it isn't, explain why. (jason) */
/* Fake this for now, just to make dwarfout.c happy. It will have to
be done in a proper way later on. */
DECL_CONTEXT (decl) = t;
+#endif
}
/* NAME is the IDENTIFIER value of a PRE_PARSED_CLASS_DECL. */
return 0;
else if (targs[idx])
{
+ tree t = targs[idx];
+ if (TREE_CODE (t) == TREE_CODE (arg))
+ switch (TREE_CODE (arg))
+ {
+ case INTEGER_CST:
+ if (tree_int_cst_equal (t, arg))
+ return 0;
+ break;
+ case REAL_CST:
+ if (REAL_VALUES_EQUAL (TREE_REAL_CST (t), TREE_REAL_CST (arg)))
+ return 0;
+ break;
+ /* STRING_CST values are not valid template const parms. */
+ default:
+ ;
+ }
my_friendly_abort (87);
return 1;
}
if (!result)
cp_error ("no matching template for `%D' found", decl);
}
+
+tree
+create_nested_upt (scope, name)
+ tree scope, name;
+{
+ tree t = make_lang_type (UNINSTANTIATED_P_TYPE);
+ tree d = build_lang_decl (TYPE_DECL, name, t);
+
+ TYPE_NAME (t) = d;
+ TYPE_VALUES (t) = TYPE_VALUES (scope);
+ TYPE_CONTEXT (t) = scope;
+
+ pushdecl (d);
+ return d;
+}
else
fputs (" X(X&)", file);
}
- if (TREE_GETS_NEW (node))
- fputs (" gets-new", file);
- if (TREE_GETS_DELETE (node))
- fputs (" gets-delete", file);
+ if (TYPE_GETS_NEW (node) & 1)
+ fputs (" new", file);
+ if (TYPE_GETS_NEW (node) & 2)
+ fputs (" new[]", file);
+ if (TYPE_GETS_DELETE (node) & 1)
+ fputs (" delete", file);
+ if (TYPE_GETS_DELETE (node) & 2)
+ fputs (" delete[]", file);
if (TYPE_HAS_ASSIGNMENT (node))
fputs (" has=", file);
if (TYPE_HAS_ASSIGN_REF (node))
if (TREE_CODE (rval) == CONST_DECL)
{
if (this_v == access_private)
- errstr = "enum `%s' is a private value of class `%s'";
+ errstr = "enum `%D' is a private value of class `%T'";
else if (this_v == access_protected)
- errstr = "enum `%s' is a protected value of class `%s'";
+ errstr = "enum `%D' is a protected value of class `%T'";
}
else
{
if (this_v == access_private)
- errstr = "member `%s' is a private member of class `%s'";
+ errstr = "member `%D' is a private member of class `%T'";
else if (this_v == access_protected)
- errstr = "member `%s' is a protected member of class `%s'";
+ errstr = "member `%D' is a protected member of class `%T'";
}
}
else
{
/* This is ambiguous. */
- errstr = "request for member `%s' is ambiguous";
+ errstr = "request for member `%D' is ambiguous";
protect = 2;
break;
}
new_v = compute_access (TREE_VALUE (TREE_CHAIN (*tp)), rval);
if (this_v != access_default && new_v != this_v)
{
- errstr = "conflicting access to member `%s'";
+ errstr = "conflicting access to member `%D'";
this_v = access_default;
}
own_access = new_v;
if (errstr == 0)
{
if (own_access == access_private)
- errstr = "member `%s' declared private";
+ errstr = "member `%D' declared private";
else if (own_access == access_protected)
- errstr = "member `%s' declared protected";
+ errstr = "member `%D' declared protected";
else if (this_v == access_private)
errstr = TREE_PRIVATE (rval)
- ? "member `%s' is private"
- : "member `%s' is from private base class";
+ ? "member `%D' is private"
+ : "member `%D' is from private base class";
else if (this_v == access_protected)
errstr = TREE_PROTECTED (rval)
- ? "member `%s' is protected"
- : "member `%s' is from protected base class";
+ ? "member `%D' is protected"
+ : "member `%D' is from protected base class";
}
if (entry)
if (errstr && protect)
{
- char *p = IDENTIFIER_POINTER (name), *q = NULL;
- if (IDENTIFIER_OPNAME_P (name))
- {
- q = operator_name_string (name);
- p = (char *) xmalloc (9 + strlen (q) + 1);
- sprintf (p, "operator %s", q);
- }
-
- error (errstr, p, TYPE_NAME_STRING (type));
- if (q)
- free (p);
+ cp_error (errstr, name, type);
rval = error_mark_node;
}
return rval;
search_stack = push_search_level (search_stack, &search_obstack);
id = TYPE_IDENTIFIER (type);
+#if 0
if (IDENTIFIER_TEMPLATE (id) != 0)
{
-#if 0
tree tmpl = IDENTIFIER_TEMPLATE (id);
push_template_decls (DECL_ARGUMENTS (TREE_PURPOSE (tmpl)),
TREE_VALUE (tmpl), 1);
-#endif
overload_template_name (id, 1);
}
+#endif
/* Push class fields into CLASS_VALUE scope, and mark. */
dfs_walk (TYPE_BINFO (type), dfs_pushdecls, unmarkedp);
n_outer_fields_searched = 0;
n_contexts_saved = 0;
}
+
+tree
+lookup_nested_tag (type, name)
+ tree type, name;
+{
+ tree tags = CLASSTYPE_TAGS (type);
+
+ for (; tags; tags = TREE_CHAIN (tags))
+ {
+ /* The TREE_PURPOSE of an enum tag (which becomes a member of the
+ enclosing class) is set to the name for the enum type. So, if
+ name is `bar', and we strike `baz' for `enum bar { baz }', then
+ this test will be true. */
+ if (TREE_PURPOSE (tags) == name)
+ break;
+ }
+ if (tags)
+ return TYPE_NAME (TREE_VALUE (tags));
+
+ if (TYPE_CONTEXT (type))
+ return lookup_nested_tag (TYPE_CONTEXT (type), name);
+
+ return NULL_TREE;
+}
};
static int do_aggr ();
-static struct token frob_identifier ();
-static tree hack_more_ids ();
-#if 0
-static struct token hack_scope ();
-static tree hack_ptype ();
-#endif
/* From lex.c: */
/* the declaration found for the last IDENTIFIER token read in.
static int debug_yychar ();
#endif
-#if 0 /* Used by arbitrate_lookup */
-static char follows_typename[END_OF_SAVED_INPUT+1];
-static char follows_identifier[END_OF_SAVED_INPUT+1];
-#endif
-
-/* This is a hack!!! TEMPLATE_TYPE_SEEN_BEFORE_SCOPE consists of the name
- * of the last template_type parsed in parse.y if it is followed by a
- * scope operator. It will be reset inside the next invocation of yylex().
- * This is used for recognizing nested types inside templates.
- * - niklas@appli.se */
-tree template_type_seen_before_scope;
-
/* Initialize token_obstack. Called once, from init_lex. */
void
init_spew ()
{
-#if 0 /* Used by arbitrate_lookup */
- static char *chars_following_identifier = ".+-|/%^!?:";
- short *ps;
- static short toks_follow_ids[] =
- { ASSIGN, RANGE, OROR, ANDAND, MIN_MAX, EQCOMPARE,
- ARITHCOMPARE, LSHIFT, RSHIFT, UNARY, PLUSPLUS, MINUSMINUS, POINTSAT,
- POINTSAT_STAR, DOT_STAR, CONSTANT, STRING, SIZEOF, ENUM, IF,
- ELSE, WHILE, DO, FOR, SWITCH, CASE, DEFAULT, BREAK, CONTINUE,
- RETURN, GOTO, ASM_KEYWORD, GCC_ASM_KEYWORD, TYPEOF, ALIGNOF, HEADOF,
- CLASSOF, SIGOF, ATTRIBUTE, AGGR, VISSPEC, DELETE, RAISE, RERAISE, TRY,
- EXCEPT, CATCH, THROW, ANSI_TRY, ANSI_THROW, DYNAMIC_CAST, TYPEID,
- EXTERN_LANG_STRING, ALL, END_OF_SAVED_INPUT, -1 };
- static short toks_follow_types[] =
- { IDENTIFIER, TYPENAME, SCOPED_TYPENAME, SCOPED_NAME, SCSPEC,
- TYPESPEC, TYPE_QUAL,
- ELLIPSIS, THIS, OPERATOR, TEMPLATE, SCOPE, START_DECLARATOR,
- TYPENAME_COLON, PAREN_STAR_PAREN, TYPENAME_ELLIPSIS, PTYPENAME,
- PRE_PARSED_FUNCTION_DECL, PRE_PARSED_CLASS_DECL, -1 };
-
- /* Initialize the arrays saying what tokens are definitely
- (or possibly) valid following typenames and identifiers. */
- while (*chars_following_identifier)
- follows_identifier[*chars_following_identifier++] = 1;
- for (ps = toks_follow_ids; *ps != -1; ps++)
- follows_identifier[*ps] = 1;
- for (ps = toks_follow_types; *ps != -1; ps++)
- follows_typename[*ps] = 1;
-#endif
-
gcc_obstack_init(&token_obstack);
}
: first_token++)
#endif
-/* Pull in enough tokens from real_yylex that the queue is N long. */
+/* Pull in enough tokens from real_yylex that the queue is N long beyond
+ the current token. */
static void
scan_tokens (n)
}
/* from lex.c: */
-/* Value is 1 if we should try to make the next identifier look like a
- typename (when it may be a local variable or a class variable).
- Value is 0 if we treat this name in a default fashion.
- Value is -1 if we must not see a type name. */
+/* Value is 1 (or 2) if we should try to make the next identifier look like
+ a typename (when it may be a local variable or a class variable).
+ Value is 0 if we treat this name in a default fashion. */
extern int looking_for_typename;
extern struct obstack *current_obstack, *saveable_obstack;
+tree got_scope;
int
yylex()
fprintf(stderr, "\t\t## %d ##",yylex_ctr);
}
#endif
-
- /* This is a kludge for recognizing nested types in templates */
- if (template_type_seen_before_scope)
- {
- shift_tokens (2); /* Sync in hack_more_ids (yes, it's ugly) */
- nth_token (1)->yychar = SCOPE;
- yylval.ttype = hack_more_ids (0, template_type_seen_before_scope);
- template_type_seen_before_scope = 0;
- if (!yylval.ttype)
- {
- /* Sync back again, leaving SCOPE on the token stream, because we
- * failed to substitute the original SCOPE token with a
- * SCOPED_TYPENAME. See rule "template_type" in parse.y */
- consume_token ();
- }
- else
- {
- tree t = TREE_TYPE(yylval.ttype);
- if (TREE_CODE(yylval.ttype) == SCOPE_REF &&
- t && TREE_CODE(t) == UNINSTANTIATED_P_TYPE)
- yychar = SCOPED_NAME;
- else
- yychar = SCOPED_TYPENAME;
-#ifdef SPEW_DEBUG
- if (spew_debug)
- debug_yychar(yychar);
-#endif
- return yychar;
- }
- }
/* if we've got tokens, send them */
if (num_tokens())
goto retry;
case IDENTIFIER:
+ scan_tokens (1);
+ if (nth_token (1)->yychar == SCOPE)
+ /* Don't interfere with the setting from an 'aggr' prefix. */
+ looking_for_typename++;
+
trrr = lookup_name (tmp_token.yylval.ttype, -2);
+
if (trrr)
{
tmp_token.yychar = identifier_type (trrr);
{
case TYPENAME:
lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype);
- if (lastiddecl == NULL_TREE)
- lastiddecl = trrr;
+ if (lastiddecl != trrr)
+ {
+ lastiddecl = trrr;
+ tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
+ }
break;
case IDENTIFIER:
lastiddecl = trrr;
break;
case PTYPENAME:
- /* This is for cases like
- template<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;
- }
+ lastiddecl = NULL_TREE;
break;
default:
my_friendly_abort (101);
/* and fall through to... */
case TYPENAME:
case PTYPENAME:
- /* if (new_token) add_token (&tmp_token); */
- *nth_token(0) = tmp_token;
- tmp_token = frob_identifier ();
- if (looking_for_typename < 0)
- {
- tmp_token.yychar = IDENTIFIER;
- lastiddecl = 0;
- looking_for_typename = 0;
- }
- else if (lastiddecl && TREE_CODE (lastiddecl) == TYPE_DECL)
- {
- scan_tokens (2);
- if (nth_token(0)->yychar == IDENTIFIER
- && nth_token (1)->yychar != SCOPE)
- looking_for_typename = -1;
- else
- looking_for_typename = 0;
- goto finish_typename_processing;
- }
- else
- looking_for_typename = 0;
+ consume_token ();
+ if (looking_for_typename > 0)
+ looking_for_typename--;
break;
case SCSPEC:
/* do_aggr needs to check if the previous token was RID_FRIEND,
so just increment first_token instead of calling consume_token. */
first_token++;
- goto finish_typename_processing;
+ break;
case TYPESPEC:
consume_token ();
- finish_typename_processing:
-#if 0
- /* Now see if we should insert a START_DECLARATOR token.
- Here are the cases caught:
-
- typespec ( * ID ) ( // ptr to function
- typespec ( & ID ) ( // ref to function
- typespec ( * ID ) [ // array of pointers
- typespec ( & ID ) [ // array of references
-
- This is a terrible kludge. */
-
- scan_tokens (2);
- if (nth_token (0)->yychar == '('
- && (nth_token (1)->yychar == '*'
- || nth_token (1)->yychar == '&'))
- {
- scan_tokens (5);
- if (nth_token (3)->yychar == ')'
- && (nth_token (4)->yychar == '('
- || nth_token (4)->yychar == '['
- || nth_token (4)->yychar == LEFT_RIGHT)
- && (nth_token (2)->yychar == IDENTIFIER
- || nth_token (2)->yychar == TYPENAME))
- {
- shift_tokens (1);
- nth_token (0)->yychar = START_DECLARATOR;
- }
- }
- /* Extend to handle:
-
- typespec (ID::* qf)( // ptr to member function
- typespec (ID::* qf)[ // array of ptr to member functions
-
- */
- if (nth_token (0)->yychar == '('
- && (nth_token (1)->yychar == IDENTIFIER
- || nth_token (1)->yychar == TYPENAME))
- {
- scan_tokens (7);
- if (nth_token (2)->yychar == SCOPE
- && nth_token (3)->yychar == '*'
- && (nth_token (4)->yychar == IDENTIFIER
- || nth_token (4)->yychar == TYPENAME)
- && nth_token (5)->yychar == ')'
- && (nth_token (6)->yychar == '('
- || nth_token (6)->yychar == '['
- || nth_token (6)->yychar == LEFT_RIGHT))
- {
- shift_tokens (1);
- nth_token (0)->yychar = START_DECLARATOR;
- }
- }
-#endif
break;
-#if 0
- case '(':
- /* Handle casts. We are looking for one of:
- `( TYPENAME' followed by `)', or
- `( TYPENAME *' followed by one of `[,*,&,)', or
- `( TYPENAME &' followed by one of `[,*,&,)', or
- `( TYPENAME [' followed by `]'. We are punting
- generality on scanning casts to array types. */
- scan_tokens (4);
- if (nth_token (1)->yychar == IDENTIFIER)
- {
- tree type = identifier_typedecl_value (nth_token (1)->yylval.ttype);
- if (type)
- switch (nth_token (2)->yychar)
- {
- default:
- break;
- }
- }
- break;
-
- case SCOPE:
- /* if (new_token) add_token (&tmp_token); */
- *nth_token(0) = tmp_token;
- tmp_token = hack_scope ();
- break;
-#endif
-
case AGGR:
*nth_token(0) = tmp_token;
do_aggr ();
looking_for_typename = 1;
/* fall through... */
default:
-#ifdef SPEW_DEBUG
- if (spew_debug)
- debug_yychar(tmp_token.yychar);
-#endif
consume_token();
- yylval = tmp_token.yylval;
- yychar = tmp_token.yychar;
- end_of_file = tmp_token.end_of_file;
- return tmp_token.yychar;
- }
-
- if (tmp_token.yychar == SCOPED_TYPENAME)
- {
-#if 0
- tree t2 = resolve_scope_to_name (NULL_TREE, tmp_token.yylval.ttype);
- if (t2 != NULL_TREE)
- {
- tmp_token.yylval.ttype = t2;
- tmp_token.yychar = TYPENAME;
- }
- else
- {
- /* unwind? */
- }
- }
- else
- {
- /* couldn't get here, as is... */
-#endif
- tmp_token.yychar = TYPENAME;
}
yylval = tmp_token.yylval;
if (spew_debug)
debug_yychar(yychar);
#endif
-/* consume_token(); */ /* already eaten by frob_identifier?... */
return yychar;
}
}
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
/* debug_yychar takes a yychar (token number) value and prints its name. */