cp-tree.def (PTRMEM_CST): New tree node.

* cp-tree.def (PTRMEM_CST): New tree node.
	* cp-tree.h (ptrmem_cst): New type.
	(lang_type): Remove local_typedecls.
	(dummy): Increase to 12 bits from 11.
	(CLASSTYPE_LOCAL_TYPEDECLS): Remove.
	(PTRMEM_CST_CLASS): New macro.
	(PTRMEM_CST_MEMBER): Likewise.
	(current_access_specifier): New variable.
	(current_class_type): Remove duplicate declaration.
	(finish_struct): Change prototype.
	(unreverse_member_declarations): New function.
	(pushdecl_class_level): Change prototype.
	(grok_enum_decls): Remove.
	(fixup_anonymous_union): New function.
	(grok_x_components): Change prototype.
	(tsubst_chain): Remove.
	(finish_member_template_decl): Likewise.
	(check_explicit_specialization): Fix indentation.
	(finish_class_definition): Change prototype.
	(finish_member_class_template): Likewise.
	(finish_member_declaration): New function.
	(check_multiple_declarators): Likewise.
	* class.c (class_stack_node_t): New type.
	(current_class_base): Remove.
	(current_class_stack): Change type.
	(current_access_specifier): New variable.
	(grow_method): Remove.
	(check_member_decl_is_same_in_complete_scope): Break out from
	finish_struct.
	(make_method_vec): New function.
	(free_method_vec): Likewise.
	(add_implicitly_declared_members): Break out from finish_struct_1.
	(free_method_vecs): New variable.
	(add_method): Rework for direct use from parser.
	(handle_using_decl): Watch for NULL_TREE while iterating through
	CLASSTYPE_METHOD_VEC.
	(finish_struct_methods): Don't build CLASSTYPE_METHOD_VEC here;
	just do some error-checking.
	(warn_hidden): Change iteration through CLASSTYPE_METHOD_VEC.
	(finish_struct_1): Simplify.  Use add_implicitly_declared_members.
	(finish_struct): Change prototype.  Simplify; fields and methods
	are already set up at this point.
	(init_class_processing): Set up current_class_stack.
	(pushclass): Save current_access_specifier.
	(popclass): Restore it.
	(currently_open_class): Simplify.
	(build_self_reference): Remove use of CLASSTYPE_LOCAL_TYPEDECLS.
	* decl.c (saved_scope): Add access_specifier.
	(maybe_push_to_top_level): Save it.
	(pop_from_top_level): Restore it.
	(maybe_process_template_type_declaration): Use
	finish_member_declaration.
	(pushtag): Likewise.
	(pushdecl_class_level): Don't return a value.
	(fixup_anonymous_union): Break out from grok_x_components.
	(shadow_tag): Use it.
	(xref_tag): Complain about using an elaborated type specifier to
	reference a template type parameter or typedef name.
	(xref_basetypes): Don't set CLASSTYPE_LOCAL_TYPEDECLS.
	(current_local_enum): Remove.
	(build_enumerator): Call finish_member_declaration.
	(grok_enum_decls): Remove.
	* decl2.c (grok_x_components): Simplify.
	(check_classfn): Change iteration through CLASSTYPE_METHOD_VEC.
	(grokfield): Don't set CLASSTYPE_LOCAL_TYPEDECLS.
	(merge_functions): Add to comment.
	(arg_assoc_type): Prototype.
	(arg_assoc): Pass as many arguments as there are parameters.
	* error.c (dump_expr): Handle PTRMEM_CST.  Improve handling of
	OFFSET_REF.
	* expr.c (cpls_expand_expr): Remove dead code.  Handle
	PTRMEM_CST.
	* friend.c (do_friend): Lookup friends when in nested classes.
	Change comments.
	* init.c (build_offset_ref): Do lookup even for classes that are
	only partially defined.
	(decl_constant_value): Remove dead code.
	* method.c (build_overload_value): Remove hack where by TYPE was
	not a TYPE.  Handle PTRMEM_CST.
	(build_template_parm_names): Don't pass a PARM_DECL where a TYPE
	should go.
	* parse.y (components, notype_components, component_decl,
	component_decl_1, component_declarator, component_declarator0):
	Now all are itype rather than ttype.  Rework to add members to
	classes on the fly.
	(typesqpecqual_reserved): Use check_multiple_declarators.
	(structsp): Update class to finish_class_definition.
	(do_xref_defn): Unsplit into named_class_head.
	(access_specifier): Set current_access_specifier.
	* pt.c (set_current_access_from_decl): New function.
	(finish_member_template_decl): Don't take the parameters.
	(comp_template_args): Make more robust.
	(lookup_template_class): Don't use current_local_enum.
	(for_each_template_parm): Handle PTRMEM_CST.
	(instantiate_class_template): Use set_current_access_from_decl,
	finish_member_declaration and unreverse_member_declarations.  Set
	lineno/input_filename before generating implicit member functions.
	(type_unification_real): Don't assume back-unification happens
	only for the last argument.
	(regenerate_decl_from_template): Call pushclass a bit earlier.
	(tsubst_chain): Remove.
	(tsubst_enum): Use set_current_access_from_decl.
	(set_mangled_name_for_template_decl): Fix indentation.
	* search.c (lookup_fnfields_1): Change iteration through
	CLASSTYPE_METHOD_VEC.
	(dfs_pushdecls): Likewise.
	(dfs_compress_decls): Likewise.
	(add_conversions): Likewise.
	* semantics.c (finish_class_definition): Don't take components.
	Change call to finish_struct.
	(finish_member_declaration): New function.
	(finish_member_class_template): Don't take template parameters.
	Change call to grok_x_components.  Call finish_member_template_decl.
	(check_multiple_declarators): New function.
	* sig.c (append_signature_fields): Work from the TYPE_METHODS, not
	a passed in fieldlist.
	* tree.c (search_tree): Handle PTRMEM_CST.
	(mapcar): Likewise.
	* typeck.c (unary_complex_lvalue): Build PTRMEM_CSTs, not
	INTEGER_CSTs, for pointer-to-data members.

From-SVN: r22869
This commit is contained in:
Mark Mitchell 1998-10-06 14:20:30 +00:00 committed by Mark Mitchell
parent 1c9a32c2d5
commit 61a127b3d1
27 changed files with 4657 additions and 4309 deletions

View File

@ -1,5 +1,126 @@
1998-10-06 Mark Mitchell <mark@markmitchell.com>
* cp-tree.def (PTRMEM_CST): New tree node.
* cp-tree.h (ptrmem_cst): New type.
(lang_type): Remove local_typedecls.
(dummy): Increase to 12 bits from 11.
(CLASSTYPE_LOCAL_TYPEDECLS): Remove.
(PTRMEM_CST_CLASS): New macro.
(PTRMEM_CST_MEMBER): Likewise.
(current_access_specifier): New variable.
(current_class_type): Remove duplicate declaration.
(finish_struct): Change prototype.
(unreverse_member_declarations): New function.
(pushdecl_class_level): Change prototype.
(grok_enum_decls): Remove.
(fixup_anonymous_union): New function.
(grok_x_components): Change prototype.
(tsubst_chain): Remove.
(finish_member_template_decl): Likewise.
(check_explicit_specialization): Fix indentation.
(finish_class_definition): Change prototype.
(finish_member_class_template): Likewise.
(finish_member_declaration): New function.
(check_multiple_declarators): Likewise.
* class.c (class_stack_node_t): New type.
(current_class_base): Remove.
(current_class_stack): Change type.
(current_access_specifier): New variable.
(grow_method): Remove.
(check_member_decl_is_same_in_complete_scope): Break out from
finish_struct.
(make_method_vec): New function.
(free_method_vec): Likewise.
(add_implicitly_declared_members): Break out from finish_struct_1.
(free_method_vecs): New variable.
(add_method): Rework for direct use from parser.
(handle_using_decl): Watch for NULL_TREE while iterating through
CLASSTYPE_METHOD_VEC.
(finish_struct_methods): Don't build CLASSTYPE_METHOD_VEC here;
just do some error-checking.
(warn_hidden): Change iteration through CLASSTYPE_METHOD_VEC.
(finish_struct_1): Simplify. Use add_implicitly_declared_members.
(finish_struct): Change prototype. Simplify; fields and methods
are already set up at this point.
(init_class_processing): Set up current_class_stack.
(pushclass): Save current_access_specifier.
(popclass): Restore it.
(currently_open_class): Simplify.
(build_self_reference): Remove use of CLASSTYPE_LOCAL_TYPEDECLS.
* decl.c (saved_scope): Add access_specifier.
(maybe_push_to_top_level): Save it.
(pop_from_top_level): Restore it.
(maybe_process_template_type_declaration): Use
finish_member_declaration.
(pushtag): Likewise.
(pushdecl_class_level): Don't return a value.
(fixup_anonymous_union): Break out from grok_x_components.
(shadow_tag): Use it.
(xref_tag): Complain about using an elaborated type specifier to
reference a template type parameter or typedef name.
(xref_basetypes): Don't set CLASSTYPE_LOCAL_TYPEDECLS.
(current_local_enum): Remove.
(build_enumerator): Call finish_member_declaration.
(grok_enum_decls): Remove.
* decl2.c (grok_x_components): Simplify.
(check_classfn): Change iteration through CLASSTYPE_METHOD_VEC.
(grokfield): Don't set CLASSTYPE_LOCAL_TYPEDECLS.
(merge_functions): Add to comment.
(arg_assoc_type): Prototype.
(arg_assoc): Pass as many arguments as there are parameters.
* error.c (dump_expr): Handle PTRMEM_CST. Improve handling of
OFFSET_REF.
* expr.c (cpls_expand_expr): Remove dead code. Handle
PTRMEM_CST.
* friend.c (do_friend): Lookup friends when in nested classes.
Change comments.
* init.c (build_offset_ref): Do lookup even for classes that are
only partially defined.
(decl_constant_value): Remove dead code.
* method.c (build_overload_value): Remove hack where by TYPE was
not a TYPE. Handle PTRMEM_CST.
(build_template_parm_names): Don't pass a PARM_DECL where a TYPE
should go.
* parse.y (components, notype_components, component_decl,
component_decl_1, component_declarator, component_declarator0):
Now all are itype rather than ttype. Rework to add members to
classes on the fly.
(typesqpecqual_reserved): Use check_multiple_declarators.
(structsp): Update class to finish_class_definition.
(do_xref_defn): Unsplit into named_class_head.
(access_specifier): Set current_access_specifier.
* pt.c (set_current_access_from_decl): New function.
(finish_member_template_decl): Don't take the parameters.
(comp_template_args): Make more robust.
(lookup_template_class): Don't use current_local_enum.
(for_each_template_parm): Handle PTRMEM_CST.
(instantiate_class_template): Use set_current_access_from_decl,
finish_member_declaration and unreverse_member_declarations. Set
lineno/input_filename before generating implicit member functions.
(type_unification_real): Don't assume back-unification happens
only for the last argument.
(regenerate_decl_from_template): Call pushclass a bit earlier.
(tsubst_chain): Remove.
(tsubst_enum): Use set_current_access_from_decl.
(set_mangled_name_for_template_decl): Fix indentation.
* search.c (lookup_fnfields_1): Change iteration through
CLASSTYPE_METHOD_VEC.
(dfs_pushdecls): Likewise.
(dfs_compress_decls): Likewise.
(add_conversions): Likewise.
* semantics.c (finish_class_definition): Don't take components.
Change call to finish_struct.
(finish_member_declaration): New function.
(finish_member_class_template): Don't take template parameters.
Change call to grok_x_components. Call finish_member_template_decl.
(check_multiple_declarators): New function.
* sig.c (append_signature_fields): Work from the TYPE_METHODS, not
a passed in fieldlist.
* tree.c (search_tree): Handle PTRMEM_CST.
(mapcar): Likewise.
* typeck.c (unary_complex_lvalue): Build PTRMEM_CSTs, not
INTEGER_CSTs, for pointer-to-data members.
* call.c (resolve_args): Resolve template specializations, if
possible.

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,11 @@ Boston, MA 02111-1307, USA. */
just won't work for us. */
DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2)
/* A pointer-to-member constant. For a pointer-to-member constant
`X::Y' The PTRMEM_CST_CLASS is the RECORD_TYPE for `X' and the
PTRMEM_CST_MEMBER is the _DECL for `Y'. */
DEFTREECODE (PTRMEM_CST, "ptrmem_cst", 'c', 1)
/* For NEW_EXPR, operand 0 is the placement list.
Operand 1 is the new-declarator.
Operand 2 is the initializer. */

View File

@ -109,6 +109,12 @@ typedef struct
tree decl;
} template_parm_index;
typedef struct ptrmem_cst
{
char common[sizeof (struct tree_common)];
tree member;
}* ptrmem_cst_t;
/* For a binding between a name and an entity, defines the scope
where the binding is declared. Currently always points to a
namespace declaration. */
@ -586,7 +592,6 @@ struct lang_type
unsigned has_call_overloaded : 1;
unsigned has_array_ref_overloaded : 1;
unsigned has_arrow_overloaded : 1;
unsigned local_typedecls : 1;
unsigned interface_only : 1;
unsigned interface_unknown : 1;
@ -625,7 +630,7 @@ struct lang_type
/* 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 : 11;
unsigned dummy : 12;
} type_flags;
int n_ancestors;
@ -786,7 +791,12 @@ struct lang_type
hierarchy, then we can use more efficient search techniques. */
#define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3(NODE))
/* List of lists of member functions defined in this class. */
/* Vector member functions defined in this class. Each element is
either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD. The first
two elements are for constructors, and destructors, respectively.
Any user-defined conversion operators follow these. These are
followed by ordinary member functions. There may be empty entries
at the end of the vector. */
#define CLASSTYPE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods)
/* The first type conversion operator in the class (the others can be
@ -900,9 +910,6 @@ struct lang_type
the virtual function table will be written out. */
#define CLASSTYPE_VTABLE_NEEDS_WRITING(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.vtable_needs_writing)
/* Nonzero means that this type defines its own local type declarations. */
#define CLASSTYPE_LOCAL_TYPEDECLS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.local_typedecls)
/* Nonzero means that this type has an X() constructor. */
#define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_default_ctor)
@ -1508,6 +1515,17 @@ extern int flag_new_for_scope;
#define DELTA2_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, NULL_TREE, 0), delta2_identifier, NULL_TREE, 0))
#define PFN_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, NULL_TREE, 0), pfn_identifier, NULL_TREE, 0))
/* For a pointer-to-member constant `X::Y' this is the RECORD_TYPE for
`X'. */
#define PTRMEM_CST_CLASS(NODE) \
(TYPE_PTRMEM_P (TREE_TYPE (NODE)) \
? TYPE_OFFSET_BASETYPE (TREE_TYPE (NODE)) \
: TYPE_PTRMEMFUNC_OBJECT_TYPE (TREE_TYPE (NODE)))
/* For a pointer-to-member constant `X::Y' this is the _DECL for
`Y'. */
#define PTRMEM_CST_MEMBER(NODE) (((ptrmem_cst_t) NODE)->member)
/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was
specified in its declaration. */
#define DECL_THIS_EXTERN(NODE) (DECL_LANG_FLAG_2(NODE))
@ -1853,6 +1871,7 @@ extern void constant_expression_warning PROTO((tree));
extern tree convert_and_check PROTO((tree, tree));
extern void overflow_warning PROTO((tree));
extern void unsigned_conversion_warning PROTO((tree, tree));
/* Read the rest of the current #-directive line. */
#if USE_CPPLIB
extern char *get_directive_line PROTO((void));
@ -1957,6 +1976,13 @@ extern int minimal_parse_mode;
extern void maybe_print_template_context PROTO ((void));
/* in class.c */
/* When parsing a class definition, the access specifier most recently
given by the user, or, if no access specifier was given, the
default value appropriate for the kind of class (i.e., struct,
class, or union). */
extern tree current_access_specifier;
extern tree current_class_name;
extern tree current_class_type;
extern tree current_class_ptr;
@ -2257,7 +2283,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
/* The following two can be derived from the previous one */
extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */
extern tree current_class_type; /* _TYPE: the type of the current class */
/* Some macros for char-based bitfields. */
#define B_SET(a,x) (a[x>>3] |= (1 << (x&7)))
@ -2414,7 +2439,7 @@ extern void add_method PROTO((tree, tree *, tree));
extern int currently_open_class PROTO((tree));
extern tree get_vfield_offset PROTO((tree));
extern void duplicate_tag_error PROTO((tree));
extern tree finish_struct PROTO((tree, tree, tree, int));
extern tree finish_struct PROTO((tree, tree, int));
extern tree finish_struct_1 PROTO((tree, int));
extern int resolves_to_fixed_type_p PROTO((tree, int *));
extern void init_class_processing PROTO((void));
@ -2433,6 +2458,7 @@ extern tree build_self_reference PROTO((void));
extern void warn_hidden PROTO((tree));
extern tree get_enclosing_class PROTO((tree));
int is_base_of_enclosing_class PROTO((tree, tree));
extern void unreverse_member_declarations PROTO((tree));
/* in cvt.c */
extern tree convert_to_reference PROTO((tree, tree, int, int, tree));
@ -2488,7 +2514,7 @@ extern int decls_match PROTO((tree, tree));
extern int duplicate_decls PROTO((tree, tree));
extern tree pushdecl PROTO((tree));
extern tree pushdecl_top_level PROTO((tree));
extern tree pushdecl_class_level PROTO((tree));
extern void pushdecl_class_level PROTO((tree));
#if 0
extern void pushdecl_nonclass_level PROTO((tree));
#endif
@ -2551,7 +2577,6 @@ extern void xref_basetypes PROTO((tree, tree, tree, tree));
extern tree start_enum PROTO((tree));
extern tree finish_enum PROTO((tree));
extern tree build_enumerator PROTO((tree, tree, tree));
extern tree grok_enum_decls PROTO((tree));
extern int start_function PROTO((tree, tree, tree, int));
extern void expand_start_early_try_stmts PROTO((void));
extern void store_parm_decls PROTO((void));
@ -2572,13 +2597,14 @@ extern void replace_defarg PROTO((tree, tree));
extern void print_other_binding_stack PROTO((struct binding_level *));
extern void revert_static_member_fn PROTO((tree*, tree*, tree*));
extern void cat_namespace_levels PROTO((void));
extern void fixup_anonymous_union PROTO((tree));
/* in decl2.c */
extern int check_java_method PROTO((tree));
extern int lang_decode_option PROTO((int, char **));
extern tree grok_method_quals PROTO((tree, tree, tree));
extern void warn_if_unknown_interface PROTO((tree));
extern tree grok_x_components PROTO((tree, tree));
extern void grok_x_components PROTO((tree));
extern void maybe_retrofit_in_chrg PROTO((tree));
extern void maybe_make_one_only PROTO((tree));
extern void grokclassfn PROTO((tree, tree, enum overload_flags, tree));
@ -2787,10 +2813,9 @@ extern tree innermost_args PROTO ((tree));
extern tree tsubst PROTO ((tree, tree, tree));
extern tree tsubst_expr PROTO ((tree, tree, tree));
extern tree tsubst_copy PROTO ((tree, tree, tree));
extern tree tsubst_chain PROTO((tree, tree));
extern void maybe_begin_member_template_processing PROTO((tree));
extern void maybe_end_member_template_processing PROTO((void));
extern tree finish_member_template_decl PROTO((tree, tree));
extern tree finish_member_template_decl PROTO((tree));
extern void begin_template_parm_list PROTO((void));
extern void begin_specialization PROTO((void));
extern void reset_specialization PROTO((void));
@ -2798,7 +2823,7 @@ extern void end_specialization PROTO((void));
extern void begin_explicit_instantiation PROTO((void));
extern void end_explicit_instantiation PROTO((void));
extern tree determine_specialization PROTO((tree, tree, tree *, int, int));
extern tree check_explicit_specialization PROTO((tree, tree, int, int));
extern tree check_explicit_specialization PROTO((tree, tree, int, int));
extern tree process_template_parm PROTO((tree, tree));
extern tree end_template_parm_list PROTO((tree));
extern void end_template_decl PROTO((void));
@ -2950,14 +2975,16 @@ extern tree finish_template_type_parm PROTO((tree, tree));
extern tree finish_template_template_parm PROTO((tree, tree));
extern tree finish_parmlist PROTO((tree, int));
extern tree begin_class_definition PROTO((tree));
extern tree finish_class_definition PROTO((tree, tree, tree, int));
extern tree finish_class_definition PROTO((tree, tree, int));
extern void finish_default_args PROTO((void));
extern void begin_inline_definitions PROTO((void));
extern tree finish_member_class_template PROTO((tree, tree));
extern tree finish_member_class_template PROTO((tree));
extern void finish_template_decl PROTO((tree));
extern tree finish_template_type PROTO((tree, tree, int));
extern void enter_scope_of PROTO((tree));
extern tree finish_base_specifier PROTO((tree, tree, int));
extern void finish_member_declaration PROTO((tree));
extern void check_multiple_declarators PROTO((void));
/* in sig.c */
extern tree build_signature_pointer_type PROTO((tree));

View File

@ -1896,7 +1896,9 @@ struct saved_scope {
tree old_bindings;
tree old_namespace;
struct saved_scope *prev;
tree class_name, class_type, function_decl;
tree class_name, class_type;
tree access_specifier;
tree function_decl;
struct binding_level *class_bindings;
tree *lang_base, *lang_stack, lang_name;
int lang_stacksize;
@ -2010,6 +2012,7 @@ maybe_push_to_top_level (pseudo)
s->old_namespace = current_namespace;
s->class_name = current_class_name;
s->class_type = current_class_type;
s->access_specifier = current_access_specifier;
s->function_decl = current_function_decl;
s->class_bindings = class_binding_level;
s->lang_stack = current_lang_stack;
@ -2091,6 +2094,7 @@ pop_from_top_level ()
current_namespace = s->old_namespace;
current_class_name = s->class_name;
current_class_type = s->class_type;
current_access_specifier = s->access_specifier;
current_function_decl = s->function_decl;
class_binding_level = s->class_bindings;
free (current_lang_base);
@ -2297,6 +2301,7 @@ maybe_process_template_type_declaration (type, globalize, b)
{
pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
b->level_chain);
finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
/* Put this tag on the list of tags for the class, since
that won't happen below because B is not the class
binding level, but is instead the pseudo-global level. */
@ -2391,7 +2396,15 @@ pushtag (name, type, globalize)
globalize, b);
if (b->parm_flag == 2)
d = pushdecl_class_level (d);
{
pushdecl_class_level (d);
if (newdecl && !PROCESSING_REAL_TEMPLATE_DECL_P ())
/* Put this TYPE_DECL on the TYPE_FIELDS list for the
class. But if it's a member template class, we
want the TEMPLATE_DECL, not the TYPE_DECL, so this
is done later. */
finish_member_declaration (d);
}
else
d = pushdecl_with_scope (d, b);
@ -3788,7 +3801,7 @@ pushdecl_top_level (x)
/* Make the declaration of X appear in CLASS scope. */
tree
void
pushdecl_class_level (x)
tree x;
{
@ -3839,7 +3852,6 @@ pushdecl_class_level (x)
set_identifier_type_value (name, TREE_TYPE (x));
}
}
return x;
}
#if 0
@ -6291,6 +6303,48 @@ define_function (name, type, function_code, pfn, library_name)
return decl;
}
/* When we call finish_struct for an anonymous union, we create
default copy constructors and such. But, an anonymous union
shouldn't have such things; this function undoes the damage to the
anonymous union type T.
(The reason that we create the synthesized methods is that we don't
distinguish `union { int i; }' from `typedef union { int i; } U'.
The first is an anonymous union; the second is just an ordinary
union type.) */
void
fixup_anonymous_union (t)
tree t;
{
tree *q;
/* Wipe out memory of synthesized methods */
TYPE_HAS_CONSTRUCTOR (t) = 0;
TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
TYPE_HAS_INIT_REF (t) = 0;
TYPE_HAS_CONST_INIT_REF (t) = 0;
TYPE_HAS_ASSIGN_REF (t) = 0;
TYPE_HAS_ASSIGNMENT (t) = 0;
TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
/* Splice the implicitly generated functions out of the TYPE_METHODS
list. */
q = &TYPE_METHODS (t);
while (*q)
{
if (DECL_ARTIFICIAL (*q))
*q = TREE_CHAIN (*q);
else
q = &TREE_CHAIN (*q);
}
/* ANSI C++ June 5 1992 WP 9.5.3. Anonymous unions may not have
function members. */
if (TYPE_METHODS (t))
error ("an anonymous union cannot have function members");
}
/* Called when a declaration is seen that contains no names to declare.
If its type is a reference to a structure, union or enum inherited
from a containing scope, shadow that tag name for the current scope
@ -6349,31 +6403,7 @@ shadow_tag (declspecs)
|| (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))))
{
/* See also grok_x_components. */
tree *q;
/* Wipe out memory of synthesized methods */
TYPE_HAS_CONSTRUCTOR (t) = 0;
TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
TYPE_HAS_INIT_REF (t) = 0;
TYPE_HAS_CONST_INIT_REF (t) = 0;
TYPE_HAS_ASSIGN_REF (t) = 0;
TYPE_HAS_ASSIGNMENT (t) = 0;
TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
q = &TYPE_METHODS (t);
while (*q)
{
if (DECL_ARTIFICIAL (*q))
*q = TREE_CHAIN (*q);
else
q = &TREE_CHAIN (*q);
}
/* ANSI C++ June 5 1992 WP 9.5.3. Anonymous unions may not have
function members. */
if (TYPE_METHODS (t))
error ("an anonymous union cannot have function members");
fixup_anonymous_union (t);
if (TYPE_FIELDS (t))
{
@ -9714,6 +9744,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type = TREE_TYPE (type);
}
/* Merge any constancy or volatility into the target type
for the pointer. */
/* We now know that constp and volatilep don't apply to the
decl, but to the target of the pointer. */
constp = volatilep = 0;
@ -10040,6 +10073,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
{
/* FIXME: This is bogus; we should not be doing this for
cv-qualified types. */
/* For anonymous structs that are cv-qualified, need to use
TYPE_MAIN_VARIANT so that name will mangle correctly. As
type not referenced after this block, don't bother
@ -10094,9 +10130,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
error ("non-object member `%s' cannot be declared mutable", name);
}
error ("non-object member `%s' cannot be declared mutable", name);
bad_specifiers (decl, "type", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@ -11477,6 +11511,7 @@ xref_tag (code_type_node, name, globalize)
}
else
t = IDENTIFIER_TYPE_VALUE (name);
if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM
&& TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM)
t = NULL_TREE;
@ -11651,6 +11686,19 @@ xref_tag (code_type_node, name, globalize)
TREE_TYPE (ref) = attributes;
if (ref && TYPE_P (ref))
{
/* [dcl.type.elab]
If the identifier resolves to a typedef-name or a template
type-parameter, the elaborated-type-specifier is
ill-formed. */
if (TYPE_LANG_SPECIFIC (ref) && TYPE_WAS_ANONYMOUS (ref))
cp_error ("`%T' is a typedef name", ref);
else if (TREE_CODE (ref) == TEMPLATE_TYPE_PARM)
cp_error ("`%T' is a template type paramter", ref);
}
return ref;
}
@ -11791,7 +11839,6 @@ xref_basetypes (code_type_node, name, ref, binfo)
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;
}
}
@ -11817,8 +11864,6 @@ xref_basetypes (code_type_node, name, ref, binfo)
}
tree current_local_enum = NULL_TREE;
/* Begin compiling the definition of an enumeration type.
NAME is its name (or null if anonymous).
Returns the type object, as yet incomplete.
@ -11858,8 +11903,6 @@ start_enum (name)
if (current_class_type)
TREE_ADDRESSABLE (b->tags) = 1;
current_local_enum = NULL_TREE;
/* We don't copy this value because build_enumerator needs to do it. */
enum_next_value = integer_zero_node;
enum_overflow = 0;
@ -12079,8 +12122,10 @@ build_enumerator (name, value, type)
if (context && context == current_class_type)
{
pushdecl_class_level (decl);
TREE_CHAIN (decl) = current_local_enum;
current_local_enum = decl;
/* In something like `struct S { enum E { i = 7 }; };' we put `i'
on the TYPE_FIELDS list for `S'. (That's so that you can say
things like `S::i' later.) */
finish_member_declaration (decl);
}
else
{
@ -12100,47 +12145,6 @@ build_enumerator (name, value, type)
return result;
}
/* Called after we have finished the declaration of an enumeration
type, and, perhaps, some objects whose type involves the
enumeration type. DECL, if non-NULL, is the declaration of the
first such object.
If CURRENT_LOCAL_ENUM is NULL, the DECL is returned.
If CURRENT_LOCAL_ENUM is non-NULL, it should be the CONST_DECL for
the last enumeration constant of an enumeration type that is a
member of a class. The enumeration constants are already chained
together through their TREE_CHAIN fields. This function sets the
TREE_CHAIN of the last enumeration constant to DECL. The
CONST_DECL for the last enumeration constant is returned.
CURRENT_LOCAL_ENUM will always be NULL when this function
returns. */
tree
grok_enum_decls (decl)
tree decl;
{
tree d = current_local_enum;
if (d == NULL_TREE)
return decl;
while (1)
{
if (TREE_CHAIN (d) == NULL_TREE)
{
TREE_CHAIN (d) = decl;
break;
}
d = TREE_CHAIN (d);
}
decl = current_local_enum;
current_local_enum = NULL_TREE;
return decl;
}
static int function_depth;

View File

@ -860,123 +860,37 @@ warn_if_unknown_interface (decl)
/* A subroutine of the parser, to handle a component list. */
tree
grok_x_components (specs, components)
tree specs, components;
void
grok_x_components (specs)
tree specs;
{
register tree t, x, tcode;
struct pending_inline **p;
tree t;
/* We just got some friends. They have been recorded elsewhere. */
if (components == void_type_node)
return NULL_TREE;
if (components == NULL_TREE)
t = groktypename (build_decl_list (strip_attrs (specs), NULL_TREE));
if (t == NULL_TREE)
{
t = groktypename (build_decl_list (strip_attrs (specs),
NULL_TREE));
if (t == NULL_TREE)
{
error ("error in component specification");
return NULL_TREE;
}
switch (TREE_CODE (t))
{
case VAR_DECL:
/* Static anonymous unions come out as VAR_DECLs. */
if (ANON_UNION_TYPE_P (TREE_TYPE (t)))
return t;
/* We return SPECS here, because in the parser it was ending
up with not doing anything to $$, which is what SPECS
represents. */
return specs;
break;
case RECORD_TYPE:
case UNION_TYPE:
if (TREE_CODE (t) == UNION_TYPE)
tcode = union_type_node;
else
tcode = record_type_node;
if (CLASSTYPE_DECLARED_CLASS (t))
tcode = class_type_node;
else if (IS_SIGNATURE (t))
tcode = signature_type_node;
if (TYPE_LANG_SPECIFIC (t)
&& CLASSTYPE_USE_TEMPLATE (t))
/* We have already looked up this type. */
;
else
{
if (CLASSTYPE_IS_TEMPLATE (t))
x = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
else
x = TYPE_IDENTIFIER (t);
t = xref_tag (tcode, x, 0);
}
if (ANON_UNION_TYPE_P (t))
{
/* See also shadow_tag. */
struct pending_inline **p;
tree *q;
x = build_lang_field_decl (FIELD_DECL, NULL_TREE, t);
/* Wipe out memory of synthesized methods */
TYPE_HAS_CONSTRUCTOR (t) = 0;
TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
TYPE_HAS_INIT_REF (t) = 0;
TYPE_HAS_CONST_INIT_REF (t) = 0;
TYPE_HAS_ASSIGN_REF (t) = 0;
TYPE_HAS_ASSIGNMENT (t) = 0;
TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
q = &TYPE_METHODS (t);
while (*q)
{
if (DECL_ARTIFICIAL (*q))
*q = TREE_CHAIN (*q);
else
q = &TREE_CHAIN (*q);
}
if (TYPE_METHODS (t))
error ("an anonymous union cannot have function members");
p = &pending_inlines;
for (; *p; *p = (*p)->next)
if (DECL_CONTEXT ((*p)->fndecl) != t)
break;
return x;
}
return NULL_TREE;
break;
case ENUMERAL_TYPE:
tcode = enum_type_node;
t = xref_tag (tcode, TYPE_IDENTIFIER (t), 0);
x = grok_enum_decls (NULL_TREE);
return x;
break;
default:
if (t != void_type_node)
error ("empty component declaration");
return NULL_TREE;
}
cp_error ("invalid member declaration");
return;
}
else
/* There may or may not be any enum decls to grok, but
grok_enum_decls will just return components, if there aren't
any. We used to try to figure out whether or not there were
any enum decls based on the type of components, but that's too
hard; it might be something like `enum { a } *p;'. */
return grok_enum_decls (components);
/* The only case where we need to do anything additional here is an
anonymous union field, e.g.: `struct S { union { int i; }; };'. */
if (!ANON_UNION_TYPE_P (t))
return;
fixup_anonymous_union (t);
finish_member_declaration (build_lang_field_decl (FIELD_DECL,
NULL_TREE,
t));
/* Ignore any inline function definitions in the anonymous union
since an anonymous union may not have function members. */
p = &pending_inlines;
for (; *p; *p = (*p)->next)
if (DECL_CONTEXT ((*p)->fndecl) != t)
break;
}
/* Constructors for types with virtual baseclasses need an "in-charge" flag
@ -1459,7 +1373,7 @@ check_classfn (ctype, function)
&& DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)))
goto got_it;
while (++methods != end)
while (++methods != end && *methods)
{
fndecl = *methods;
if (fn_name == DECL_NAME (OVL_CURRENT (*methods)))
@ -1530,14 +1444,12 @@ check_classfn (ctype, function)
if (templates)
/* This function might be an instantiation or a specialization.
We should verify that this is possible. If it is, we must
somehow add the new declaration to the method vector for the
class. Perhaps we should use add_method? For now, we simply
return NULL_TREE, which lets the caller know that this
function is new, but we don't print an error message. */
We should verify that this is possible. For now, we simply
return NULL_TREE, which lets the caller know that this function
is new, but we don't print an error message. */
return NULL_TREE;
if (methods != end)
if (methods != end && *methods)
{
tree fndecl = *methods;
cp_error ("prototype for `%#D' does not match any in class `%T'",
@ -1640,7 +1552,6 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
DECL_NONLOCAL (value) = 1;
DECL_CONTEXT (value) = current_class_type;
DECL_CLASS_CONTEXT (value) = current_class_type;
CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1;
/* Now that we've updated the context, we need to remangle the
name for this TYPE_DECL. */
@ -4129,7 +4040,9 @@ add_using_namespace (user, used, indirect)
/* Combines two sets of overloaded functions into an OVERLOAD chain, removing
duplicates. The first list becomes the tail of the result.
The algorithm is O(n^2). */
The algorithm is O(n^2). We could get this down to O(n log n) by
doing a sort on the addresses of the functions, if that becomes
necessary. */
static tree
merge_functions (s1, s2)
@ -4414,6 +4327,7 @@ struct arg_lookup
static int arg_assoc PROTO((struct arg_lookup*, tree));
static int arg_assoc_args PROTO((struct arg_lookup*, tree));
static int arg_assoc_type PROTO((struct arg_lookup*, tree));
/* Add a function to the lookup structure.
Returns 1 on error. */
@ -4662,7 +4576,7 @@ arg_assoc (k, n)
return 1;
}
else if (TREE_CODE_CLASS (TREE_CODE (t)) == 't'
&& arg_assoc_type (t) == 1)
&& arg_assoc_type (k, t) == 1)
return 1;
}
}

View File

@ -1265,6 +1265,13 @@ dump_expr (t, nop)
OB_PUTCP (digit_buffer);
break;
case PTRMEM_CST:
OB_PUTC ('&');
dump_type (PTRMEM_CST_CLASS (t), 0);
OB_PUTS ("::");
OB_PUTID (DECL_NAME (PTRMEM_CST_MEMBER (t)));
break;
case STRING_CST:
{
char *p = TREE_STRING_POINTER (t);
@ -1571,10 +1578,14 @@ dump_expr (t, nop)
{
tree ob = TREE_OPERAND (t, 0);
if (TREE_CODE (ob) == NOP_EXPR
&& TREE_OPERAND (ob, 0) == error_mark_node
&& TREE_CODE (TREE_OPERAND (t, 1)) == FUNCTION_DECL)
/* A::f */
dump_expr (TREE_OPERAND (t, 1), 0);
&& TREE_OPERAND (ob, 0) == error_mark_node)
{
if (TREE_CODE (TREE_OPERAND (t, 1)) == FUNCTION_DECL)
/* A::f */
dump_expr (TREE_OPERAND (t, 1), 0);
else
dump_decl (TREE_OPERAND (t, 1), 0);
}
else
{
dump_expr (TREE_OPERAND (t, 0), 0);

View File

@ -162,19 +162,43 @@ cplus_expand_expr (exp, target, tmode, modifier)
return DECL_RTL (slot);
}
case PTRMEM_CST:
{
tree member;
tree offset;
/* Find the member. */
member = PTRMEM_CST_MEMBER (exp);
if (TREE_CODE (member) == FIELD_DECL)
{
/* Find the offset for the field. */
offset = convert (sizetype,
size_binop (EASY_DIV_EXPR,
DECL_FIELD_BITPOS (member),
size_int (BITS_PER_UNIT)));
/* We offset all pointer to data members by 1 so that we
can distinguish between a null pointer to data member
and the first data member of a structure. */
offset = size_binop (PLUS_EXPR, offset, size_int (1));
return expand_expr (cp_convert (type, offset), target, tmode,
modifier);
}
else
{
/* We don't yet handle pointer-to-member functions this
way. */
my_friendly_abort (0);
return 0;
}
}
case OFFSET_REF:
{
#if 1
return expand_expr (default_conversion (resolve_offset_ref (exp)),
target, tmode, EXPAND_NORMAL);
#else
/* This is old crusty code, and does not handle all that the
resolve_offset_ref function does. (mrs) */
tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0);
tree offset = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
return expand_expr (build (PLUS_EXPR, TREE_TYPE (exp), base, offset),
target, tmode, EXPAND_NORMAL);
#endif
}
case THUNK_DECL:

View File

@ -372,21 +372,22 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
if (is_friend_template)
decl = DECL_TI_TEMPLATE (push_template_decl (decl));
if (TYPE_SIZE (ctype) != 0 && template_class_depth (ctype) == 0)
decl = check_classfn (ctype, decl);
/* TYPE_BEING_DEFINED is a hack for nested classes having
member functions of the enclosing class as friends. Will
go away as parsing of classes gets rewritten. */
if (TREE_TYPE (decl) != error_mark_node)
/* A nested class may declare a member of an enclosing class
to be a friend, so we do lookup here even if CTYPE is in
the process of being defined. */
if (TYPE_SIZE (ctype) != 0 || TYPE_BEING_DEFINED (ctype))
{
if (TYPE_BEING_DEFINED (ctype) ||
TYPE_SIZE (ctype) || template_class_depth (ctype) > 0)
/* But, we defer looup in template specializations until
they are fully specialized. */
if (template_class_depth (ctype) == 0)
decl = check_classfn (ctype, decl);
if (decl)
add_friend (current_class_type, decl);
else
cp_error ("member `%D' declared as friend before type `%T' defined",
decl, ctype);
}
else
cp_error ("member `%D' declared as friend before type `%T' defined",
decl, ctype);
}
else
{

View File

@ -1561,30 +1561,11 @@ build_offset_ref (type, name)
name = ctor_identifier;
#endif
if (TYPE_SIZE (complete_type (type)) == 0)
if (TYPE_SIZE (complete_type (type)) == 0
&& !TYPE_BEING_DEFINED (type))
{
if (type == current_class_type)
t = IDENTIFIER_CLASS_VALUE (name);
else
t = NULL_TREE;
if (t == 0)
{
cp_error ("incomplete type `%T' does not have member `%D'", type,
name);
return error_mark_node;
}
if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == VAR_DECL
|| TREE_CODE (t) == CONST_DECL)
{
mark_used (t);
return t;
}
if (TREE_CODE (t) == FIELD_DECL)
sorry ("use of member in incomplete aggregate type");
else if (TREE_CODE (t) == FUNCTION_DECL)
sorry ("use of member function in incomplete aggregate type");
else
my_friendly_abort (52);
cp_error ("incomplete type `%T' does not have member `%D'", type,
name);
return error_mark_node;
}
@ -1883,28 +1864,14 @@ decl_constant_value (decl)
tree decl;
{
if (! TREE_THIS_VOLATILE (decl)
#if 0
/* These may be necessary for C, but they break C++. */
! TREE_PUBLIC (decl)
/* Don't change a variable array bound or initial value to a constant
in a place where a variable is invalid. */
&& ! pedantic
#endif /* 0 */
&& DECL_INITIAL (decl) != 0
&& DECL_INITIAL (decl)
&& DECL_INITIAL (decl) != error_mark_node
/* This is invalid if initial value is not constant.
If it has either a function call, a memory reference,
or a variable, then re-evaluating it could give different results. */
&& TREE_CONSTANT (DECL_INITIAL (decl))
/* Check for cases where this is sub-optimal, even though valid. */
&& TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR
#if 0
/* We must allow this to work outside of functions so that
static constants can be used for array sizes. */
&& current_function_decl != 0
&& DECL_MODE (decl) != BLKmode
#endif
)
&& TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
return DECL_INITIAL (decl);
return decl;
}

View File

@ -628,15 +628,12 @@ build_overload_value (type, value, in_template)
tree type, value;
int in_template;
{
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (type)) == 't', 0);
while (TREE_CODE (value) == NON_LVALUE_EXPR
|| TREE_CODE (value) == NOP_EXPR)
value = TREE_OPERAND (value, 0);
if (TREE_CODE (type) == PARM_DECL)
type = TREE_TYPE (type);
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (type)) == 't', 0);
if (numeric_output_need_bar)
{
OB_PUTC ('_');
@ -649,17 +646,20 @@ build_overload_value (type, value, in_template)
return;
}
if (TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
if (TYPE_PTRMEM_P (type))
{
/* Handle a pointer to data member as a template instantiation
parameter, boy, what fun! */
type = integer_type_node;
if (TREE_CODE (value) != INTEGER_CST)
{
sorry ("unknown pointer to member constant");
return;
}
if (TREE_CODE (value) != PTRMEM_CST)
/* We should have already rejected this pointer to member,
since it is not a constant. */
my_friendly_abort (0);
/* Get the actual FIELD_DECL. */
value = PTRMEM_CST_MEMBER (value);
my_friendly_assert (TREE_CODE (value) == FIELD_DECL, 0);
/* Output the name of the field. */
build_overload_identifier (DECL_NAME (value));
return;
}
if (TYPE_PTRMEMFUNC_P (type))
@ -898,7 +898,8 @@ build_template_parm_names (parmlist, arglist)
parm = tsubst (parm, arglist, NULL_TREE);
/* It's a PARM_DECL. */
build_mangled_name_for_type (TREE_TYPE (parm));
build_overload_value (parm, arg, uses_template_parms (arglist));
build_overload_value (TREE_TYPE (parm), arg,
uses_template_parms (arglist));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -204,10 +204,9 @@ empty_parms ()
%type <ttype> declarator notype_declarator after_type_declarator
%type <ttype> direct_notype_declarator direct_after_type_declarator
%type <ttype> opt.component_decl_list component_decl_list
%type <ttype> component_decl component_decl_1 components notype_components
%type <ttype> component_declarator component_declarator0 self_reference
%type <itype> components notype_components
%type <ttype> component_decl component_decl_1
%type <ttype> component_declarator component_declarator0
%type <ttype> notype_component_declarator notype_component_declarator0
%type <ttype> after_type_component_declarator after_type_component_declarator0
%type <ttype> enumlist enumerator
@ -1844,16 +1843,19 @@ typespecqual_reserved:
initdecls:
initdcl0
| initdecls ',' initdcl
{ check_multiple_declarators (); }
;
notype_initdecls:
notype_initdcl0
| notype_initdecls ',' initdcl
{ check_multiple_declarators (); }
;
nomods_initdecls:
nomods_initdcl0
| nomods_initdecls ',' initdcl
{ check_multiple_declarators (); }
;
maybeasm:
@ -2112,7 +2114,7 @@ structsp:
yychar = YYLEX;
semi = yychar == ';';
$<ttype>$ = finish_class_definition ($1, $3, $5, semi);
$<ttype>$ = finish_class_definition ($1, $5, semi);
}
pending_defargs
{ finish_default_args (); }
@ -2168,7 +2170,10 @@ aggr:
named_class_head_sans_basetype:
aggr identifier
{ current_aggr = $$; $$ = $2; }
{
current_aggr = $1;
$$ = $2;
}
;
named_class_head_sans_basetype_defn:
@ -2202,15 +2207,11 @@ named_complex_class_head_sans_basetype:
{ current_aggr = $$; $$ = $3; }
;
do_xref_defn:
/* empty */ %prec EMPTY
{ $<ttype>$ = xref_tag (current_aggr, $<ttype>0, 0); }
;
named_class_head:
named_class_head_sans_basetype %prec EMPTY
{ $$ = xref_tag (current_aggr, $1, 1); }
| named_class_head_sans_basetype_defn do_xref_defn
| named_class_head_sans_basetype_defn
{ $<ttype>$ = xref_tag (current_aggr, $1, 0); }
maybe_base_class_list %prec EMPTY
{
$$ = $<ttype>2;
@ -2358,64 +2359,45 @@ left_curly:
self_reference:
/* empty */
{
$$ = build_self_reference ();
finish_member_declaration (build_self_reference ());
}
;
opt.component_decl_list:
self_reference
{ if ($$) $$ = build_tree_list (access_public_node, $$); }
| self_reference component_decl_list
{
if (current_aggr == signature_type_node)
$$ = build_tree_list (access_public_node, $2);
else
$$ = build_tree_list (access_default_node, $2);
if ($1) $$ = tree_cons (access_public_node, $1, $$);
}
| opt.component_decl_list VISSPEC ':' component_decl_list
{
tree visspec = $2;
| opt.component_decl_list access_specifier component_decl_list
| opt.component_decl_list access_specifier
;
access_specifier:
VISSPEC ':'
{
if (current_aggr == signature_type_node)
{
error ("access specifier not allowed in signature");
visspec = access_public_node;
$1 = access_public_node;
}
$$ = chainon ($$, build_tree_list (visspec, $4));
}
| opt.component_decl_list VISSPEC ':'
{
if (current_aggr == signature_type_node)
error ("access specifier not allowed in signature");
}
current_access_specifier = $1;
}
;
/* Note: we no longer warn about the semicolon after a component_decl_list.
ARM $9.2 says that the semicolon is optional, and therefore allowed. */
component_decl_list:
component_decl
{ if ($$ == void_type_node) $$ = NULL_TREE;
{
finish_member_declaration ($1);
}
| component_decl_list component_decl
{ /* In pushdecl, we created a reverse list of names
in this binding level. Make sure that the chain
of what we're trying to add isn't the item itself
(which can happen with what pushdecl's doing). */
if ($2 != NULL_TREE && $2 != void_type_node
&& $2 != error_mark_node)
{
if (TREE_CHAIN ($2) != $$)
$$ = chainon ($$, $2);
else
$$ = $2;
}
{
finish_member_declaration ($2);
}
;
component_decl:
component_decl_1 ';'
{ }
| component_decl_1 '}'
{ error ("missing ';' before right brace");
yyungetc ('}', 0); }
@ -2435,9 +2417,20 @@ component_decl:
{ $$ = $2;
pedantic = $<itype>1; }
| template_header component_decl
{ $$ = finish_member_template_decl ($1, $2); }
{
if ($2)
$$ = finish_member_template_decl ($2);
else
/* The component was already processed. */
$$ = NULL_TREE;
finish_template_decl ($1);
}
| template_header typed_declspecs ';'
{ $$ = finish_member_class_template ($1, $2.t); }
{
$$ = finish_member_class_template ($2.t);
finish_template_decl ($1);
}
;
component_decl_1:
@ -2445,9 +2438,32 @@ component_decl_1:
speed; we need to call grok_x_components for enums, so the
speedup would be insignificant. */
typed_declspecs components
{ $$ = grok_x_components ($1.t, $2); }
{
/* Most of the productions for component_decl only
allow the creation of one new member, so we call
finish_member_declaration in component_decl_list.
For this rule and the next, however, there can be
more than one member, e.g.:
int i, j;
and we need the first member to be fully
registered before the second is processed.
Therefore, the rules for components take care of
this processing. To avoid registering the
components more than once, we send NULL_TREE up
here; that lets finish_member_declaration now
that there is nothing to do. */
if (!$2)
grok_x_components ($1.t);
$$ = NULL_TREE;
}
| declmods notype_components
{ $$ = grok_x_components ($1, $2); }
{
if (!$2)
grok_x_components ($1);
$$ = NULL_TREE;
}
| notype_declarator maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, NULL_TREE, $4, $2,
build_tree_list ($3, NULL_TREE)); }
@ -2482,31 +2498,41 @@ component_decl_1:
/* ??? Huh? ^^^ */
components:
/* empty: possibly anonymous */
{ $$ = NULL_TREE; }
{ $$ = 0; }
| component_declarator0
{
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
$1 = finish_member_template_decl ($1);
finish_member_declaration ($1);
$$ = 1;
}
| components ',' component_declarator
{
/* In this context, void_type_node encodes
friends. They have been recorded elsewhere. */
if ($$ == void_type_node)
$$ = $3;
else
$$ = chainon ($$, $3);
{
check_multiple_declarators ();
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
$3 = finish_member_template_decl ($3);
finish_member_declaration ($3);
$$ = 2;
}
;
notype_components:
/* empty: possibly anonymous */
{ $$ = NULL_TREE; }
{ $$ = 0; }
| notype_component_declarator0
{
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
$1 = finish_member_template_decl ($1);
finish_member_declaration ($1);
$$ = 1;
}
| notype_components ',' notype_component_declarator
{
/* In this context, void_type_node encodes
friends. They have been recorded elsewhere. */
if ($$ == void_type_node)
$$ = $3;
else
$$ = chainon ($$, $3);
{
check_multiple_declarators ();
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
$3 = finish_member_template_decl ($3);
finish_member_declaration ($3);
$$ = 2;
}
;

View File

@ -129,6 +129,7 @@ static tree tsubst_decl PROTO((tree, tree, tree, tree));
static tree tsubst_arg_types PROTO((tree, tree, tree));
static void check_specialization_scope PROTO((void));
static tree process_partial_specialization PROTO((tree));
static void set_current_access_from_decl PROTO((tree));
/* We use TREE_VECs to hold template arguments. If there is only one
level of template arguments, then the TREE_VEC contains the
@ -196,12 +197,9 @@ static tree process_partial_specialization PROTO((tree));
it is a specialization, in which case the DECL itself is returned. */
tree
finish_member_template_decl (template_parameters, decl)
tree template_parameters;
finish_member_template_decl (decl)
tree decl;
{
finish_template_decl (template_parameters);
if (decl == NULL_TREE || decl == void_type_node)
return NULL_TREE;
else if (decl == error_mark_node)
@ -3066,9 +3064,11 @@ comp_template_args (oldargs, newargs)
if (nt == ot)
continue;
if (TREE_CODE (nt) != TREE_CODE (ot))
else if (!nt || !ot)
return 0;
if (TREE_CODE (nt) == TREE_VEC)
else if (TREE_CODE (nt) != TREE_CODE (ot))
return 0;
else if (TREE_CODE (nt) == TREE_VEC)
{
/* For member templates */
if (comp_template_args (ot, nt))
@ -3382,14 +3382,12 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
}
else
{
extern tree current_local_enum;
tree template_type = TREE_TYPE (template);
tree type_decl;
tree found = NULL_TREE;
int arg_depth;
int parm_depth;
int is_partial_instantiation;
tree prev_local_enum = NULL_TREE;
template = most_general_template (template);
parmlist = DECL_TEMPLATE_PARMS (template);
@ -3549,10 +3547,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
if (TREE_CODE (template_type) == ENUMERAL_TYPE)
{
if (!is_partial_instantiation)
{
prev_local_enum = current_local_enum;
t = start_enum (TYPE_IDENTIFIER (template_type));
}
t = start_enum (TYPE_IDENTIFIER (template_type));
else
/* We don't want to call start_enum for this type, since
the values for the enumeration constants may involve
@ -3570,7 +3565,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
TYPE_FOR_JAVA (t) = TYPE_FOR_JAVA (template_type);
}
/* If we called tsubst_enum above, this information will already
/* If we called start_enum above, this information will already
be set up. */
if (!TYPE_NAME (t))
{
@ -3599,17 +3594,14 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
if (TREE_CODE (t) == ENUMERAL_TYPE
&& !is_partial_instantiation)
{
/* Now that the type has been registered on the
instantiations list, we set up the enumerators. Because
the enumeration constants may involve the enumeration
type itself, we make sure to register the type first, and
then create the constants. That way, doing tsubst_expr
for the enumeration constants won't result in recursive
calls here; we'll find the instantiation and exit above. */
tsubst_enum (template_type, t, arglist);
current_local_enum = prev_local_enum;
}
/* Now that the type has been registered on the instantiations
list, we set up the enumerators. Because the enumeration
constants may involve the enumeration type itself, we make
sure to register the type first, and then create the
constants. That way, doing tsubst_expr for the enumeration
constants won't result in recursive calls here; we'll find
the instantiation and exit above. */
tsubst_enum (template_type, t, arglist);
/* We're done with the permanent obstack, now. */
pop_obstacks ();
@ -3814,6 +3806,9 @@ for_each_template_parm (t, fn, data)
case TYPENAME_TYPE:
return 1;
case PTRMEM_CST:
return for_each_template_parm (TREE_TYPE (t), fn, data);
case SCOPE_REF:
return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
@ -4256,7 +4251,7 @@ tree
instantiate_class_template (type)
tree type;
{
tree template, args, pattern, t, *field_chain;
tree template, args, pattern, t;
tree typedecl;
if (type == error_mark_node)
@ -4323,11 +4318,16 @@ instantiate_class_template (type)
}
if (pedantic && uses_template_parms (args))
/* If there are still template parameters amongst the args, then
we can't instantiate the type; there's no telling whether or not one
of the template parameters might eventually be instantiated to some
value that results in a specialization being used. */
return type;
{
/* If there are still template parameters amongst the args, then
we can't instantiate the type; there's no telling whether or not one
of the template parameters might eventually be instantiated to some
value that results in a specialization being used. We do the
type as complete so that, for example, declaring one of its
members to be a friend will not be rejected. */
TYPE_SIZE (type) = integer_zero_node;
return type;
}
TYPE_BEING_DEFINED (type) = 1;
@ -4394,8 +4394,6 @@ instantiate_class_template (type)
TYPE_ALIGN (type) = TYPE_ALIGN (pattern);
TYPE_FOR_JAVA (type) = TYPE_FOR_JAVA (pattern); /* For libjava's JArray<T> */
CLASSTYPE_LOCAL_TYPEDECLS (type) = CLASSTYPE_LOCAL_TYPEDECLS (pattern);
/* If this is a partial instantiation, don't tsubst anything. We will
only use this type for implicit typename, so the actual contents don't
matter. All that matters is whether a particular name is a type. */
@ -4449,8 +4447,6 @@ instantiate_class_template (type)
}
TYPE_GETS_NEW (type) |= TYPE_GETS_NEW (basetype);
TYPE_GETS_DELETE (type) |= TYPE_GETS_DELETE (basetype);
CLASSTYPE_LOCAL_TYPEDECLS (type)
|= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
}
/* Don't initialize this until the vector is filled out, or
lookups will crash. */
@ -4458,8 +4454,6 @@ instantiate_class_template (type)
}
}
field_chain = &TYPE_FIELDS (type);
for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t))
{
tree tag = TREE_VALUE (t);
@ -4467,35 +4461,7 @@ instantiate_class_template (type)
tree newtag;
newtag = tsubst (tag, args, NULL_TREE);
if (TREE_CODE (newtag) == ENUMERAL_TYPE)
{
extern tree current_local_enum;
tree prev_local_enum = current_local_enum;
if (TYPE_VALUES (newtag))
{
tree v;
/* We must set things up so that CURRENT_LOCAL_ENUM is the
CONST_DECL for the last enumeration constant, since the
CONST_DECLs are chained backwards. */
for (v = TYPE_VALUES (newtag); TREE_CHAIN (v);
v = TREE_CHAIN (v))
;
current_local_enum
= IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (v));
*field_chain = grok_enum_decls (NULL_TREE);
current_local_enum = prev_local_enum;
while (*field_chain)
{
DECL_FIELD_CONTEXT (*field_chain) = type;
field_chain = &TREE_CHAIN (*field_chain);
}
}
}
else
if (TREE_CODE (newtag) != ENUMERAL_TYPE)
{
/* Now, we call pushtag to put this NEWTAG into the scope of
TYPE. We first set up the IDENTIFIER_TYPE_VALUE to avoid
@ -4530,12 +4496,27 @@ instantiate_class_template (type)
DECL_EXTERNAL (r) = 1;
cp_finish_decl (r, DECL_INITIAL (r), NULL_TREE, 0, 0);
}
*field_chain = r;
field_chain = &TREE_CHAIN (r);
/* R will have a TREE_CHAIN if and only if it has already been
processed by finish_member_declaration. This can happen
if, for example, it is a TYPE_DECL for a class-scoped
ENUMERAL_TYPE; such a thing will already have been added to
the field list by tsubst_enum above. */
if (!TREE_CHAIN (r))
{
set_current_access_from_decl (r);
finish_member_declaration (r);
}
}
TYPE_METHODS (type) = tsubst_chain (TYPE_METHODS (pattern), args);
/* Set up the list (TYPE_METHODS) and vector (CLASSTYPE_METHOD_VEC)
for this instantiation. */
for (t = TYPE_METHODS (pattern); t; t = TREE_CHAIN (t))
{
tree r = tsubst (t, args, NULL_TREE);
set_current_access_from_decl (r);
finish_member_declaration (r);
}
/* Construct the DECL_FRIENDLIST for the new class type. */
typedecl = TYPE_MAIN_DECL (type);
@ -4627,6 +4608,14 @@ instantiate_class_template (type)
require_complete_type (t);
}
/* Set the file and line number information to whatever is given for
the class itself. This puts error messages involving generated
implicit functions at a predictable point, and the same point
that would be used for non-template classes. */
lineno = DECL_SOURCE_LINE (typedecl);
input_filename = DECL_SOURCE_FILE (typedecl);
unreverse_member_declarations (type);
type = finish_struct_1 (type, 0);
CLASSTYPE_GOT_SEMICOLON (type) = 1;
@ -6787,6 +6776,7 @@ type_unification_real (tparms, targs, parms, args, subr,
{
tree targs;
tree arg_type;
int r;
/* Have to back unify here */
arg = OVL_FUNCTION (arg);
@ -6795,10 +6785,14 @@ type_unification_real (tparms, targs, parms, args, subr,
maybe_adjust_types_for_deduction (strict, &parm, &arg_type);
parm = expr_tree_cons (NULL_TREE, parm, NULL_TREE);
arg_type = scratch_tree_cons (NULL_TREE, arg_type, NULL_TREE);
return
type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg),
targs, arg_type, parm, NULL_TREE,
DEDUCE_EXACT, allow_incomplete);
r = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg),
targs, arg_type, parm, NULL_TREE,
DEDUCE_EXACT, allow_incomplete);
if (r)
/* If the back-unification failed, just bail out. */
return r;
else
continue;
}
arg = TREE_TYPE (arg);
}
@ -7952,16 +7946,22 @@ regenerate_decl_from_template (decl, tmpl)
register_specialization for it. */
my_friendly_assert (unregistered, 0);
if (TREE_CODE (decl) == VAR_DECL)
/* Make sure that we can see identifiers, and compute access
correctly, for the class members used in the declaration of
this static variable. */
pushclass (DECL_CONTEXT (decl), 2);
/* Do the substitution to get the new declaration. */
new_decl = tsubst (code_pattern, args, NULL_TREE);
if (TREE_CODE (decl) == VAR_DECL)
{
/* Set up DECL_INITIAL, since tsubst doesn't. */
pushclass (DECL_CONTEXT (decl), 2);
DECL_INITIAL (new_decl) =
tsubst_expr (DECL_INITIAL (code_pattern), args,
DECL_TI_TEMPLATE (decl));
/* Pop the class context we pushed above. */
popclass (1);
}
@ -8228,27 +8228,6 @@ out:
return d;
}
tree
tsubst_chain (t, argvec)
tree t, argvec;
{
if (t)
{
tree first = tsubst (t, argvec, NULL_TREE);
tree last = first;
for (t = TREE_CHAIN (t); t; t = TREE_CHAIN (t))
{
tree x = tsubst (t, argvec, NULL_TREE);
TREE_CHAIN (last) = x;
last = x;
}
return first;
}
return NULL_TREE;
}
static tree
tsubst_expr_values (t, argvec)
tree t, argvec;
@ -8321,6 +8300,20 @@ add_maybe_template (d, fns)
DECL_MAYBE_TEMPLATE (d) = 1;
}
/* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */
static void
set_current_access_from_decl (decl)
tree decl;
{
if (TREE_PRIVATE (decl))
current_access_specifier = access_private_node;
else if (TREE_PROTECTED (decl))
current_access_specifier = access_protected_node;
else
current_access_specifier = access_public_node;
}
/* Instantiate an enumerated type. TAG is the template type, NEWTAG
is the instantiation (which should have been created with
start_enum) and ARGS are the template arguments to use. */
@ -8335,15 +8328,20 @@ tsubst_enum (tag, newtag, args)
for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
{
tree elt
= build_enumerator (TREE_PURPOSE (e),
/* Note that in a template enum, the
TREE_VALUE is the CONST_DECL, not the
corresponding INTEGER_CST. */
tsubst_expr (DECL_INITIAL (TREE_VALUE (e)),
tree value;
tree elt;
/* Note that in a template enum, the TREE_VALUE is the
CONST_DECL, not the corresponding INTEGER_CST. */
value = tsubst_expr (DECL_INITIAL (TREE_VALUE (e)),
args,
NULL_TREE),
newtag);
NULL_TREE);
/* Give this enumeration constant the correct access. */
set_current_access_from_decl (TREE_VALUE (e));
/* Actually build the enumerator itself. */
elt = build_enumerator (TREE_PURPOSE (e), value, newtag);
/* We save the enumerators we have built so far in the
TYPE_VALUES so that if the enumeration constants for
@ -8420,7 +8418,7 @@ set_mangled_name_for_template_decl (decl)
with the innermost level omitted. */
fn_type = TREE_TYPE (tmpl);
if (DECL_STATIC_FUNCTION_P (decl))
context = DECL_CLASS_CONTEXT (decl);
context = DECL_CLASS_CONTEXT (decl);
if (parm_depth == 1)
/* No substitution is necessary. */

View File

@ -1289,7 +1289,7 @@ lookup_fnfields_1 (type, name)
if (*++methods && name == dtor_identifier)
return 1;
while (++methods != end)
while (++methods != end && *methods)
{
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
@ -1301,20 +1301,28 @@ lookup_fnfields_1 (type, name)
/* If we didn't find it, it might have been a template
conversion operator. (Note that we don't look for this case
above so that we will always find specializations first.) */
if (methods == end
if ((methods == end || !*methods)
&& IDENTIFIER_TYPENAME_P (name))
{
methods = &TREE_VEC_ELT (method_vec, 0) + 1;
while (++methods != end)
while (++methods != end && *methods)
{
if (TREE_CODE (OVL_CURRENT (*methods)) == TEMPLATE_DECL
&& IDENTIFIER_TYPENAME_P (DECL_NAME (OVL_CURRENT (*methods))))
tree method_name = DECL_NAME (OVL_CURRENT (*methods));
if (!IDENTIFIER_TYPENAME_P (method_name))
{
/* Since all conversion operators come first, we know
there is no such operator. */
methods = end;
break;
}
else if (TREE_CODE (OVL_CURRENT (*methods)) == TEMPLATE_DECL)
break;
}
}
if (methods != end)
if (methods != end && *methods)
return methods - &TREE_VEC_ELT (method_vec, 0);
}
@ -2962,7 +2970,7 @@ dfs_pushdecls (binfo)
tree binfo;
{
tree type = BINFO_TYPE (binfo);
tree fields, *methods, *end;
tree fields;
tree method_vec;
int dummy = 0;
@ -3015,16 +3023,24 @@ dfs_pushdecls (binfo)
method_vec = CLASSTYPE_METHOD_VEC (type);
if (method_vec && ! dummy)
{
tree *methods;
tree *end;
/* Farm out constructors and destructors. */
methods = &TREE_VEC_ELT (method_vec, 2);
end = TREE_VEC_END (method_vec);
while (methods != end)
for (methods = &TREE_VEC_ELT (method_vec, 2);
*methods && methods != end;
methods++)
{
/* This will cause lookup_name to return a pointer
to the tree_list of possible methods of this name. */
tree name = DECL_NAME (OVL_CURRENT (*methods));
tree class_value = IDENTIFIER_CLASS_VALUE (name);
tree name;
tree class_value;
name = DECL_NAME (OVL_CURRENT (*methods));
class_value = IDENTIFIER_CLASS_VALUE (name);
/* If the class value is not an envelope of the kind described in
the comment above, we create a new envelope. */
@ -3049,8 +3065,6 @@ dfs_pushdecls (binfo)
envelope_add_decl (type, OVL_CURRENT (*methods),
&TREE_PURPOSE (class_value));
pop_obstacks ();
methods++;
}
}
@ -3074,10 +3088,11 @@ dfs_compress_decls (binfo)
else if (method_vec != 0)
{
/* Farm out constructors and destructors. */
tree *methods = &TREE_VEC_ELT (method_vec, 2);
tree *methods;
tree *end = TREE_VEC_END (method_vec);
for (; methods != end; methods++)
for (methods = &TREE_VEC_ELT (method_vec, 2);
methods != end && *methods; methods++)
{
/* This is known to be an envelope of the kind described before
dfs_pushdecls. */
@ -3269,7 +3284,9 @@ add_conversions (binfo)
for (i = 2; i < TREE_VEC_LENGTH (method_vec); ++i)
{
tree tmp = TREE_VEC_ELT (method_vec, i);
if (! IDENTIFIER_TYPENAME_P (DECL_NAME (OVL_CURRENT (tmp))))
if (!tmp
|| !IDENTIFIER_TYPENAME_P (DECL_NAME (OVL_CURRENT (tmp))))
break;
conversions = scratch_tree_cons (binfo, tmp, conversions);
}

View File

@ -1268,14 +1268,99 @@ begin_class_definition (t)
return t;
}
/* Finish a class definition T, with the indicated COMPONENTS, and
with the indicate ATTRIBUTES. If SEMI, the definition is
immediately followed by a semicolon. Returns the type. */
/* Finish the member declaration given by DECL. */
void
finish_member_declaration (decl)
tree decl;
{
if (decl == error_mark_node || decl == NULL_TREE)
return;
if (decl == void_type_node)
/* The COMPONENT was a friend, not a member, and so there's
nothing for us to do. */
return;
/* We should see only one DECL at a time. */
my_friendly_assert (TREE_CHAIN (decl) == NULL_TREE, 0);
/* Set up access control for DECL. */
TREE_PRIVATE (decl)
= (current_access_specifier == access_private_node);
TREE_PROTECTED (decl)
= (current_access_specifier == access_protected_node);
if (TREE_CODE (decl) == TEMPLATE_DECL)
{
TREE_PRIVATE (DECL_RESULT (decl)) = TREE_PRIVATE (decl);
TREE_PROTECTED (DECL_RESULT (decl)) = TREE_PROTECTED (decl);
}
/* Mark the DECL as a member of the current class. */
if (TREE_CODE (decl) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (decl))
/* Historically, DECL_CONTEXT was not set for a FUNCTION_DECL in
finish_struct. Presumably it is already set as the function is
parsed. Perhaps DECL_CLASS_CONTEXT is already set, too? */
DECL_CLASS_CONTEXT (decl) = current_class_type;
else if (TREE_CODE (decl) == TYPE_DECL)
/* Historically, DECL_CONTEXT was not set for a TYPE_DECL in
finish_struct, so we do not do it here either. Perhaps we
should, though. */
;
else
DECL_CONTEXT (decl) = current_class_type;
/* Put functions on the TYPE_METHODS list and everything else on the
TYPE_FIELDS list. Note that these are built up in reverse order.
We reverse them (to obtain declaration order) in finish_struct. */
if (TREE_CODE (decl) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (decl))
{
/* We also need to add this function to the
CLASSTYPE_METHOD_VEC. */
add_method (current_class_type, 0, decl);
TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
TYPE_METHODS (current_class_type) = decl;
}
else
{
/* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields
go at the beginning. The reason is that lookup_field_1
searches the list in order, and we want a field name to
override a type name so that the "struct stat hack" will
work. In particular:
struct S { enum E { }; int E } s;
s.E = 3;
is legal. In addition, the FIELD_DECLs must be maintained in
declaration order so that class layout works as expected.
However, we don't need that order until class layout, so we
save a little time by putting FIELD_DECLs on in reverse order
here, and then reversing them in finish_struct_1. (We could
also keep a pointer to the correct insertion points in the
list.) */
if (TREE_CODE (decl) == TYPE_DECL)
TYPE_FIELDS (current_class_type)
= chainon (TYPE_FIELDS (current_class_type), decl);
else
{
TREE_CHAIN (decl) = TYPE_FIELDS (current_class_type);
TYPE_FIELDS (current_class_type) = decl;
}
}
}
/* Finish a class definition T with the indicate ATTRIBUTES. If SEMI,
the definition is immediately followed by a semicolon. Returns the
type. */
tree
finish_class_definition (t, components, attributes, semi)
finish_class_definition (t, attributes, semi)
tree t;
tree components;
tree attributes;
int semi;
{
@ -1299,7 +1384,7 @@ finish_class_definition (t, components, attributes, semi)
;
else
{
t = finish_struct (t, components, attributes, semi);
t = finish_struct (t, attributes, semi);
if (semi)
note_got_semicolon (t);
}
@ -1342,8 +1427,7 @@ begin_inline_definitions ()
TYPES whose template parameters are given by PARMS. */
tree
finish_member_class_template (parms, types)
tree parms;
finish_member_class_template (types)
tree types;
{
tree t;
@ -1356,13 +1440,15 @@ finish_member_class_template (parms, types)
maybe_process_partial_specialization (TREE_VALUE (t));
note_list_got_semicolon (types);
grok_x_components (types, NULL_TREE);
grok_x_components (types);
if (TYPE_CONTEXT (TREE_VALUE (types)) != current_class_type)
/* The component was in fact a friend declaration. We avoid
finish_member_template_decl performing certain checks by
unsetting TYPES. */
types = NULL_TREE;
finish_member_template_decl (parms, types);
finish_member_template_decl (types);
/* As with other component type declarations, we do
not store the new DECL on the list of
component_decls. */
@ -1480,3 +1566,31 @@ finish_base_specifier (access_specifier, base_class,
return result;
}
/* Called when multiple declarators are processed. If that is not
premitted in this context, an error is issued. */
void
check_multiple_declarators ()
{
/* [temp]
In a template-declaration, explicit specialization, or explicit
instantiation the init-declarator-list in the declaration shall
contain at most one declarator.
We don't just use PROCESSING_TEMPLATE_DECL for the first
condition since that would disallow the perfectly legal code,
like `template <class T> struct S { int i, j; };'. */
tree scope = current_scope ();
if (scope && TREE_CODE (scope) == FUNCTION_DECL)
/* It's OK to write `template <class T> void f() { int i, j;}'. */
return;
if (PROCESSING_REAL_TEMPLATE_DECL_P ()
|| processing_explicit_instantiation
|| processing_specialization)
cp_error ("multiple declarators in template declaration");
}

View File

@ -343,49 +343,45 @@ build_member_function_pointer (member)
The new FIELD_DECLs are appended at the end of the last (and only)
sublist of `list_of_fieldlists.'
T is the signature type.
As a side effect, each member function in the signature gets the
`decl.ignored' bit turned on, so we don't output debug info for it. */
void
append_signature_fields (list_of_fieldlists)
tree list_of_fieldlists;
append_signature_fields (t)
tree t;
{
tree l, x;
tree last_x = NULL_TREE;
tree x;
tree mfptr;
tree last_mfptr = NULL_TREE;
tree mfptr_list = NULL_TREE;
/* For signatures it should actually be only a list with one element. */
for (l = list_of_fieldlists; l; l = TREE_CHAIN (l))
for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
{
for (x = TREE_VALUE (l); x; x = TREE_CHAIN (x))
if (TREE_CODE (x) == FUNCTION_DECL)
{
if (TREE_CODE (x) == FUNCTION_DECL)
mfptr = build_member_function_pointer (x);
DECL_MEMFUNC_POINTER_TO (x) = mfptr;
DECL_MEMFUNC_POINTING_TO (mfptr) = x;
DECL_IGNORED_P (x) = 1;
DECL_IN_AGGR_P (mfptr) = 1;
if (! mfptr_list)
mfptr_list = last_mfptr = mfptr;
else
{
mfptr = build_member_function_pointer (x);
DECL_MEMFUNC_POINTER_TO (x) = mfptr;
DECL_MEMFUNC_POINTING_TO (mfptr) = x;
DECL_IGNORED_P (x) = 1;
DECL_IN_AGGR_P (mfptr) = 1;
if (! mfptr_list)
mfptr_list = last_mfptr = mfptr;
else
{
TREE_CHAIN (last_mfptr) = mfptr;
last_mfptr = mfptr;
}
TREE_CHAIN (last_mfptr) = mfptr;
last_mfptr = mfptr;
}
last_x = x;
}
}
/* Append the lists. */
if (last_x && mfptr_list)
{
TREE_CHAIN (last_x) = mfptr_list;
TREE_CHAIN (last_mfptr) = NULL_TREE;
}
/* The member function pointers must come after the TYPE_DECLs, in
this case, because build_signature_table_constructor depends on
finding opaque TYPE_DECLS before the functions that make use of
them. */
if (last_mfptr)
TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), mfptr_list);
}
/* Compare the types of a signature member function and a class member

View File

@ -1581,6 +1581,10 @@ search_tree (t, func)
case DEFAULT_ARG:
break;
case PTRMEM_CST:
TRY (TREE_TYPE (t));
break;
case COND_EXPR:
case TARGET_EXPR:
case AGGR_INIT_EXPR:
@ -1845,6 +1849,12 @@ mapcar (t, func)
case STRING_CST:
return copy_node (t);
case PTRMEM_CST:
t = copy_node (t);
TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
PTRMEM_CST_MEMBER (t) = mapcar (PTRMEM_CST_MEMBER (t), func);
return t;
case COND_EXPR:
case TARGET_EXPR:
case AGGR_INIT_EXPR:
@ -1908,7 +1918,7 @@ mapcar (t, func)
TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
/* tree.def says that operand two is RTL, but
build_call_declarator puts trees in there. */
make_call_declarator puts trees in there. */
if (TREE_OPERAND (t, 2)
&& TREE_CODE (TREE_OPERAND (t, 2)) == TREE_LIST)
TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
@ -2449,6 +2459,13 @@ cp_tree_equal (t1, t2)
return comptypes (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0), 1);
break;
case PTRMEM_CST:
/* Two pointer-to-members are the same if they point to the same
field or function in the same class. */
return (PTRMEM_CST_MEMBER (t1) == PTRMEM_CST_MEMBER (t2)
&& comptypes (PTRMEM_CST_CLASS (t1), PTRMEM_CST_CLASS (t2),
1));
default:
break;
}

View File

@ -4884,7 +4884,6 @@ unary_complex_lvalue (code, arg)
else
{
tree type;
tree offset;
if (TREE_OPERAND (arg, 0)
&& (TREE_CODE (TREE_OPERAND (arg, 0)) != NOP_EXPR
@ -4896,21 +4895,13 @@ unary_complex_lvalue (code, arg)
return error_mark_node;
}
/* Add in the offset to the field. */
offset = convert (sizetype,
size_binop (EASY_DIV_EXPR,
DECL_FIELD_BITPOS (t),
size_int (BITS_PER_UNIT)));
/* We offset all pointer to data members by 1 so that we can
distinguish between a null pointer to data member and the first
data member of a structure. */
offset = size_binop (PLUS_EXPR, offset, size_int (1));
type = build_offset_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t));
type = build_pointer_type (type);
return cp_convert (type, offset);
t = make_node (PTRMEM_CST);
TREE_TYPE (t) = type;
PTRMEM_CST_MEMBER (t) = TREE_OPERAND (arg, 1);
return t;
}
}

View File

@ -0,0 +1,9 @@
typedef struct {} S;
S s1;
struct S* s2; // ERROR - S is a typedef name
template <class T>
struct X {
friend class T; // ERROR - T is a template type parameter
};

View File

@ -0,0 +1,19 @@
struct S {
template <class T>
int f(T), g(T); // ERROR - more than one declarator
};
template <class T>
void x(T), y(T); // ERROR - more than one declarator
template <class T>
struct S2
{
static int i, j; // OK.
};
template <class T>
int S2<T>::i, S2<T>::j; // ERROR - more than one declarator
template <>
int S2<int>::i, S2<double>::i; // ERROR - more than one declarator

View File

@ -1,7 +1,7 @@
// Build don't link:
class foo {
friend void bar<int>(int); // ERROR - must be declared first - XFAIL *-*-*
friend void bar<int>(int); // ERROR - must be declared first
};
template <typename T> void bar(T);

View File

@ -3,4 +3,4 @@
class A
{
template<class T>T epsilon; // ERROR - invalid member template
}; // ERROR - the compiler crashes here
};

View File

@ -0,0 +1,43 @@
struct S;
template <S* (S::*p)()>
struct F {
S* f (S& s)
{
return (s.*p)();
}
};
template <int S::*p>
struct D {
void d (S& s)
{
(s.*p) = 3;
}
};
struct S {
S* g ();
int i;
F<&S::g> fg;
D<&S::i> di;
S* h(), k(F<&S::h>);
F<&S::g> fg2;
D<&S::i> di2;
};
S* S::g()
{
return this;
}
int main()
{
S s;
s.i = 2;
s.di.d (s);
if (s.i != 3)
return 1;
if (s.fg2.f(s) != &s)
return 1;
}

View File

@ -1,9 +1,9 @@
// Build don't link:
template <class A> class B { // ERROR - candidates
template <class A> class B {
A a;
public:
B(A&aa); // ERROR - near match
~B();
};
}; // ERROR - candidates
static B<int> b_int (3); // ERROR - no matching function

View File

@ -17,7 +17,7 @@ inline istream& operator>>(istream& is, Empty& ) { return is;}
template<class VertexType, class EdgeType>
class Graph
{ // ERROR - candidates
{
public:
// public type interface
typedef map<int, EdgeType > Successor;
@ -32,7 +32,7 @@ class Graph
bool directed;
GraphType C; // container
ostream* pOut;
}; // class Graph
}; // ERROR - candidates
// all graph-methods delet
template<class VertexType, class EdgeType>

View File

@ -22,7 +22,7 @@ class X
{
public:
static T *do_something ();
friend class T;
friend class T; // ERROR - `T' is a template parameter
friend class XX<T, U>;
};