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:
parent
1c9a32c2d5
commit
61a127b3d1
121
gcc/cp/ChangeLog
121
gcc/cp/ChangeLog
|
@ -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.
|
||||
|
||||
|
|
839
gcc/cp/class.c
839
gcc/cp/class.c
File diff suppressed because it is too large
Load Diff
|
@ -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. */
|
||||
|
|
|
@ -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));
|
||||
|
|
164
gcc/cp/decl.c
164
gcc/cp/decl.c
|
@ -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;
|
||||
|
||||
|
|
160
gcc/cp/decl2.c
160
gcc/cp/decl2.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
6736
gcc/cp/parse.c
6736
gcc/cp/parse.c
File diff suppressed because it is too large
Load Diff
158
gcc/cp/parse.y
158
gcc/cp/parse.y
|
@ -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;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
206
gcc/cp/pt.c
206
gcc/cp/pt.c
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
50
gcc/cp/sig.c
50
gcc/cp/sig.c
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
class A
|
||||
{
|
||||
template<class T>T epsilon; // ERROR - invalid member template
|
||||
}; // ERROR - the compiler crashes here
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue