* cp-tree.def (NEW_EXPR): Add a fourth slot.
* cp-tree.h (PARMLIST_ELLIPSIS_P): Remove.
(TREE_PARMLIST): Likewise.
(CALL_DECLARATOR_PARMS): Likewise.
(CALL_DECLARATOR_QUALS): Likewise.
(CALL_DECLARATOR_EXCEPTION_SPEC): Likewise.
(cp_declarator_kind): New type.
(cp_parameter_declarator): Likewise.
(cp_declarator): Likewise.
(cp_error_declarator): Likewise.
(no_parameters): Likewise.
(groktypename): Change prototype.
(start_decl): Likewise.
(start_handler_parms): Likewise.
(get_scope_of_declarator): Likewise.
(start_function): Likewise.
(start_preparsed_function): New function.
(start_function): Change prototype.
(start_method): Likewise.
(grokfield): Likewise.
(grokbitfield): Likewise.
(build_new): Likewise.
(make_pointer_declarator): Remove.
(make_reference_declarator): Likewise.
(make_call_declarator): Likewise.
(set_quals_and_spec): Likewise.
(process_template_parm): Change prototype.
(begin_function_definition): Remove.
(finish_parmlist): Remove.
* decl.c (groktypename): Do not use trees to represent
declarators.
(start_decl): Likewise.
(start_handler_parms): Remove.
(get_scope_of_declarator): Reimplement.
(grokdeclarator): Do not use trees to represent declarators.
(grokparms): Likewise.
(start_function): Likewise.
(start_method): Likewise.
(build_void_list_mode): Do not use TREE_PARMLIST.
* decl.h (grokdeclarator): Change prototype.
* decl2.c (grok_method_quals): Robustify.
(grok_x_components): Do not use trees to represent declarators.
(grokfield): Likewise.
(grokbitfield): Likewise.
(start_objects): Build FUNCTION_DECLs, not declarators.
(start_static_storage_duration_function): Likewise.
* init.c (build_new): Simplify.
* lex.c (make_pointer_declarator): Remove.
(make_reference_declarator): Likewise.
(make_call_declarator): Likewise.
(set_quals_and_spec): Likewise.
* method.c (use_thunk): Use start_preparsed_function.
(synthesize_method): Likewise.
(implicitly_declare_fn): Build FUNCTION_DECLs, not declarators.
* optimize.c (maybe_clone_body): Use start_preparsed_function.
* parser.c (cp_error_declarator): New variable.
(declarator_obstack): Likewise.
(alloc_declarator): New function.
(make_declarator): Likewise.
(make_id_declarator): Likewise.
(make_pointer_declarator): Likewise.
(make_reference_declarator): Likewise.
(make_ptrmem_declarator): Likewise.
(make_call_declarator): Likewise.
(make_array_declarator): Likewise.
(no_parameters): New variable.
(make_parameter_declarator): Likewise.
(cp_parser_check_for_definition_in_return_type): Do not use trees
to represent declarators.
(cp_parser_translation_unit): Likewise.
(cp_parser_new_expression): Likewise.
(cp_parser_new_type_id): Likewise.
(cp_parser_new_declarator_opt): Likewise.
(cp_parser_direct_new_declarator): Likewise.
(cp_parser_condition): Likewise.
(cp_parser_declaration_statement): Likewise.
(cp_parser_declaration): Likewise.
(cp_parser_conversion_type_id): Likewise.
(cp_parser_conversion_declarator_opt): Likewise.
(cp_parser_template_parameter_list): Likewise.
(cp_parser_template_parameter): Likewise.
(cp_parser_explicit_instantiation): Likewise.
(cp_parser_init_declarator): Likewise.
(cp_parser_declarator): Likewise.
(cp_parser_direct_declarator): Likewise.
(cp_parser_type_id): Likewise.
(cp_parser_parameter_declaration_clause): Likewise.
(cp_parser_parameter_declaration_list): Likewise.
(cp_parser_parameter_declaration): Likewise.
(cp_parser_member_declaration): Likewise.
(cp_parser_exception_declaration): Likewise.
(cp_parser_check_declarator_template_parameters): Likewise.
(cp_parser_function_definition_from_specifiers_and_declarator):
Likewise.
(cp_parser_save_member_function_body): Likewise.
* pt.c (process_template_parm): Add is_non_type parameter.
(convert_template_argument): Adjust call to groktypename.
(tsubst_call_declarator_parms): Remove use of TREE_PARMLIST.
(tsubst): Do not expect declarators.
(tsubst_copy_and_build): Adjust NEW_EXPR case to handle additional
argument.
(instantiate_decl): Use start_preparsed_function.
* semantics.c (begin_function_definition): Remove.
(finish_parmlist): Remove.
* cp-mudflap.c (mflang_flush_calls): Build FUNCTION_DECLs, not
declarators.
From-SVN: r83482
+2004-06-21 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.def (NEW_EXPR): Add a fourth slot.
+ * cp-tree.h (PARMLIST_ELLIPSIS_P): Remove.
+ (TREE_PARMLIST): Likewise.
+ (CALL_DECLARATOR_PARMS): Likewise.
+ (CALL_DECLARATOR_QUALS): Likewise.
+ (CALL_DECLARATOR_EXCEPTION_SPEC): Likewise.
+ (cp_declarator_kind): New type.
+ (cp_parameter_declarator): Likewise.
+ (cp_declarator): Likewise.
+ (cp_error_declarator): Likewise.
+ (no_parameters): Likewise.
+ (groktypename): Change prototype.
+ (start_decl): Likewise.
+ (start_handler_parms): Likewise.
+ (get_scope_of_declarator): Likewise.
+ (start_function): Likewise.
+ (start_preparsed_function): New function.
+ (start_function): Change prototype.
+ (start_method): Likewise.
+ (grokfield): Likewise.
+ (grokbitfield): Likewise.
+ (build_new): Likewise.
+ (make_pointer_declarator): Remove.
+ (make_reference_declarator): Likewise.
+ (make_call_declarator): Likewise.
+ (set_quals_and_spec): Likewise.
+ (process_template_parm): Change prototype.
+ (begin_function_definition): Remove.
+ (finish_parmlist): Remove.
+ * decl.c (groktypename): Do not use trees to represent
+ declarators.
+ (start_decl): Likewise.
+ (start_handler_parms): Remove.
+ (get_scope_of_declarator): Reimplement.
+ (grokdeclarator): Do not use trees to represent declarators.
+ (grokparms): Likewise.
+ (start_function): Likewise.
+ (start_method): Likewise.
+ (build_void_list_mode): Do not use TREE_PARMLIST.
+ * decl.h (grokdeclarator): Change prototype.
+ * decl2.c (grok_method_quals): Robustify.
+ (grok_x_components): Do not use trees to represent declarators.
+ (grokfield): Likewise.
+ (grokbitfield): Likewise.
+ (start_objects): Build FUNCTION_DECLs, not declarators.
+ (start_static_storage_duration_function): Likewise.
+ * init.c (build_new): Simplify.
+ * lex.c (make_pointer_declarator): Remove.
+ (make_reference_declarator): Likewise.
+ (make_call_declarator): Likewise.
+ (set_quals_and_spec): Likewise.
+ * method.c (use_thunk): Use start_preparsed_function.
+ (synthesize_method): Likewise.
+ (implicitly_declare_fn): Build FUNCTION_DECLs, not declarators.
+ * optimize.c (maybe_clone_body): Use start_preparsed_function.
+ * parser.c (cp_error_declarator): New variable.
+ (declarator_obstack): Likewise.
+ (alloc_declarator): New function.
+ (make_declarator): Likewise.
+ (make_id_declarator): Likewise.
+ (make_pointer_declarator): Likewise.
+ (make_reference_declarator): Likewise.
+ (make_ptrmem_declarator): Likewise.
+ (make_call_declarator): Likewise.
+ (make_array_declarator): Likewise.
+ (no_parameters): New variable.
+ (make_parameter_declarator): Likewise.
+ (cp_parser_check_for_definition_in_return_type): Do not use trees
+ to represent declarators.
+ (cp_parser_translation_unit): Likewise.
+ (cp_parser_new_expression): Likewise.
+ (cp_parser_new_type_id): Likewise.
+ (cp_parser_new_declarator_opt): Likewise.
+ (cp_parser_direct_new_declarator): Likewise.
+ (cp_parser_condition): Likewise.
+ (cp_parser_declaration_statement): Likewise.
+ (cp_parser_declaration): Likewise.
+ (cp_parser_conversion_type_id): Likewise.
+ (cp_parser_conversion_declarator_opt): Likewise.
+ (cp_parser_template_parameter_list): Likewise.
+ (cp_parser_template_parameter): Likewise.
+ (cp_parser_explicit_instantiation): Likewise.
+ (cp_parser_init_declarator): Likewise.
+ (cp_parser_declarator): Likewise.
+ (cp_parser_direct_declarator): Likewise.
+ (cp_parser_type_id): Likewise.
+ (cp_parser_parameter_declaration_clause): Likewise.
+ (cp_parser_parameter_declaration_list): Likewise.
+ (cp_parser_parameter_declaration): Likewise.
+ (cp_parser_member_declaration): Likewise.
+ (cp_parser_exception_declaration): Likewise.
+ (cp_parser_check_declarator_template_parameters): Likewise.
+ (cp_parser_function_definition_from_specifiers_and_declarator):
+ Likewise.
+ (cp_parser_save_member_function_body): Likewise.
+ * pt.c (process_template_parm): Add is_non_type parameter.
+ (convert_template_argument): Adjust call to groktypename.
+ (tsubst_call_declarator_parms): Remove use of TREE_PARMLIST.
+ (tsubst): Do not expect declarators.
+ (tsubst_copy_and_build): Adjust NEW_EXPR case to handle additional
+ argument.
+ (instantiate_decl): Use start_preparsed_function.
+ * semantics.c (begin_function_definition): Remove.
+ (finish_parmlist): Remove.
+ * cp-mudflap.c (mflang_flush_calls): Build FUNCTION_DECLs, not
+ declarators.
+
2004-06-21 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* call.c (build_vfield_ref): Add new operand for COMPONENT_REF.
mflang_flush_calls (tree enqueued_call_stmt_chain)
{
tree fnname, fndecl, body;
+ tree type;
/* Short-circuit! */
if (enqueued_call_stmt_chain == NULL_TREE)
/* Create a ctor function declaration. */
fnname = get_identifier ("__static_initialization_and_destruction_mudflap");
-
- start_function (void_list_node,
- make_call_declarator (fnname, void_list_node, NULL_TREE,
- NULL_TREE),
- NULL_TREE, SF_DEFAULT);
+ type = build_function_type (void_type_node, void_list_node);
+ fndecl = build_lang_decl (FUNCTION_DECL, fnname, type);
TREE_PUBLIC (current_function_decl) = 0;
TREE_USED (current_function_decl) = 1;
mf_mark (current_function_decl);
/* Generate the body, one statement at a time. */
+ start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
body = begin_compound_stmt (BCS_FN_BODY);
while (enqueued_call_stmt_chain)
/* For NEW_EXPR, operand 0 is the placement list.
Operand 1 is the new-declarator.
- Operand 2 is the initializer. */
-DEFTREECODE (NEW_EXPR, "nw_expr", 'e', 3)
+ Operand 2 is the number of elements in the array.
+ Operand 3 is the initializer. */
+DEFTREECODE (NEW_EXPR, "nw_expr", 'e', 4)
DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", 'e', 3)
/* For DELETE_EXPR, operand 0 is the store to be destroyed.
CLEANUP_P (in TRY_BLOCK)
AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
- PARMLIST_ELLIPSIS_P (in PARMLIST)
DECL_PRETTY_FUNCTION_P (in VAR_DECL)
KOENIG_LOOKUP_P (in CALL_EXPR)
STATEMENT_LIST_NO_SCOPE (in STATEMENT_LIST).
TYPE_POLYMORPHIC_P (in _TYPE)
ICS_THIS_FLAG (in _CONV)
BINFO_LOST_PRIMARY_P (in BINFO)
- TREE_PARMLIST (in TREE_LIST)
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
STATEMENT_LIST_TRY_BLOCK (in STATEMENT_LIST)
3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
#define BV_FN(NODE) (TREE_VALUE (NODE))
\f
-/* Nonzero for TREE_LIST node means that this list of things
- is a list of parameters, as opposed to a list of expressions. */
-#define TREE_PARMLIST(NODE) (TREE_LANG_FLAG_2 (NODE))
-
-/* Nonzero for a parmlist means that this parmlist ended in ... */
-#define PARMLIST_ELLIPSIS_P(NODE) TREE_LANG_FLAG_0 (NODE)
-
/* For FUNCTION_TYPE or METHOD_TYPE, a list of the exceptions that
this type can raise. Each TREE_VALUE is a _TYPE. The TREE_VALUE
will be NULL_TREE to indicate a throw specification of `()', or
#define THEN_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 1)
#define ELSE_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 2)
-/* The parameters for a call-declarator. */
-#define CALL_DECLARATOR_PARMS(NODE) \
- (TREE_PURPOSE (TREE_OPERAND (NODE, 1)))
-
-/* The cv-qualifiers for a call-declarator. */
-#define CALL_DECLARATOR_QUALS(NODE) \
- (TREE_VALUE (TREE_OPERAND (NODE, 1)))
-
-/* The exception-specification for a call-declarator. */
-#define CALL_DECLARATOR_EXCEPTION_SPEC(NODE) \
- (TREE_TYPE (NODE))
-
/* An enumeration of the kind of tags that C++ accepts. */
enum tag_types {
none_type = 0, /* Not a tag type. */
extern GTY(()) operator_name_info_t assignment_operator_name_info
[(int) LAST_CPLUS_TREE_CODE];
+/* The various kinds of declarators. */
+
+typedef enum cp_declarator_kind {
+ cdk_id,
+ cdk_function,
+ cdk_array,
+ cdk_pointer,
+ cdk_reference,
+ cdk_ptrmem,
+ cdk_error
+} cp_declarator_kind;
+
+/* A declarator. */
+
+typedef struct cp_declarator cp_declarator;
+
+typedef struct cp_parameter_declarator cp_parameter_declarator;
+
+/* A parameter, before it has been semantically analyzed. */
+struct cp_parameter_declarator {
+ /* The next parameter, or NULL_TREE if none. */
+ cp_parameter_declarator *next;
+ /* The decl-specifiers-seq for the parameter. */
+ tree decl_specifiers;
+ /* The declarator for the parameter. */
+ cp_declarator *declarator;
+ /* The default-argument expression, or NULL_TREE, if none. */
+ tree default_argument;
+ /* True iff this is the first parameter in the list and the
+ parameter sequence ends with an ellipsis. */
+ bool ellipsis_p;
+};
+
+/* A declarator. */
+struct cp_declarator {
+ /* The kind of declarator. */
+ cp_declarator_kind kind;
+ /* Attributes that apply to this declarator. */
+ tree attributes;
+ /* For all but cdk_id and cdk_error, the contained declarator. For
+ cdk_id and cdk_error, guaranteed to be NULL. */
+ cp_declarator *declarator;
+ union {
+ /* For identifiers. */
+ struct {
+ /* The name of the function -- an IDENTIFIER_NODE, BIT_NOT_EXPR,
+ TEMPLATE_ID_EXPR, or SCOPE_REF. */
+ tree name;
+ /* If this is the name of a function, what kind of special
+ function (if any). */
+ special_function_kind sfk;
+ } id;
+ /* For functions. */
+ struct {
+ /* The parameters to the function. */
+ cp_parameter_declarator *parameters;
+ /* The cv-qualifiers for the function. */
+ tree qualifiers;
+ /* The exception-specification for the function. */
+ tree exception_specification;
+ } function;
+ /* For arrays. */
+ struct {
+ /* The bounds to the array. */
+ tree bounds;
+ } array;
+ /* For cdk_pointer, cdk_reference, and cdk_ptrmem. */
+ struct {
+ /* The cv-qualifiers for the pointer. */
+ tree qualifiers;
+ /* For cdk_ptrmem, the class type containing the member. */
+ tree class_type;
+ } pointer;
+ } u;
+};
+
+/* An erroneous declarator. */
+extern cp_declarator *cp_error_declarator;
+
+/* A parameter list indicating for a function with no parameters,
+ e.g "int f(void)". */
+extern cp_parameter_declarator *no_parameters;
+
/* in call.c */
extern bool check_dtor_name (tree, tree);
extern int init_type_desc (void);
extern tree check_tag_decl (tree);
extern tree shadow_tag (tree);
-extern tree groktypename (tree);
-extern tree start_decl (tree, tree, int, tree, tree);
+extern tree groktypename (tree, const cp_declarator *);
+extern tree start_decl (const cp_declarator *, tree, int, tree, tree);
extern void start_decl_1 (tree);
extern void cp_finish_decl (tree, tree, tree, int);
extern void finish_decl (tree, tree, tree);
extern void maybe_inject_for_scope_var (tree);
-extern tree start_handler_parms (tree, tree);
extern int complete_array_type (tree, tree, int);
extern tree build_ptrmemfunc_type (tree);
extern tree build_ptrmem_type (tree, tree);
/* the grokdeclarator prototype is in decl.h */
extern int copy_fn_p (tree);
-extern tree get_scope_of_declarator (tree);
+extern tree get_scope_of_declarator (const cp_declarator *);
extern void grok_special_member_properties (tree);
extern int grok_ctor_properties (tree, tree);
extern bool grok_op_properties (tree, int, bool);
extern tree start_enum (tree);
extern void finish_enum (tree);
extern void build_enumerator (tree, tree, tree);
-extern int start_function (tree, tree, tree, int);
+extern void start_preparsed_function (tree, tree, int);
+extern int start_function (tree, const cp_declarator *, tree);
extern tree begin_function_body (void);
extern void finish_function_body (tree);
extern tree finish_function (int);
-extern tree start_method (tree, tree, tree);
+extern tree start_method (tree, const cp_declarator *, tree);
extern tree finish_method (tree);
extern void maybe_register_incomplete_var (tree);
extern void complete_vars (tree);
extern tree delete_sanity (tree, tree, bool, int);
extern tree check_classfn (tree, tree, tree);
extern void check_member_template (tree);
-extern tree grokfield (tree, tree, tree, tree, tree);
-extern tree grokbitfield (tree, tree, tree);
+extern tree grokfield (const cp_declarator *, tree, tree, tree, tree);
+extern tree grokbitfield (const cp_declarator *, tree, tree);
extern tree groktypefield (tree, tree);
extern void cplus_decl_attributes (tree *, tree, int);
extern void finish_anon_union (tree);
extern tree get_type_value (tree);
extern tree build_zero_init (tree, tree, bool);
extern tree build_offset_ref (tree, tree, bool);
-extern tree build_new (tree, tree, tree, int);
+extern tree build_new (tree, tree, tree, tree, int);
extern tree build_vec_init (tree, tree, tree, int);
extern tree build_x_delete (tree, int, tree);
extern tree build_delete (tree, tree, special_function_kind, int, int);
extern void initialize_vtbl_ptrs (tree);
extern tree build_java_class_ref (tree);
-/* in input.c */
-
/* in lex.c */
extern void cxx_dup_lang_specific_decl (tree);
-extern tree make_pointer_declarator (tree, tree);
-extern tree make_reference_declarator (tree, tree);
-extern tree make_call_declarator (tree, tree, tree, tree);
-extern void set_quals_and_spec (tree, tree, tree);
extern void print_parse_statistics (void);
extern void do_pending_inlines (void);
extern void yyungetc (int, int);
extern void begin_explicit_instantiation (void);
extern void end_explicit_instantiation (void);
extern tree check_explicit_specialization (tree, tree, int, int);
-extern tree process_template_parm (tree, tree);
+extern tree process_template_parm (tree, tree, bool);
extern tree end_template_parm_list (tree);
extern void end_template_decl (void);
extern tree current_template_args (void);
extern tree finish_unary_op_expr (enum tree_code, tree);
extern tree finish_compound_literal (tree, tree);
extern tree finish_fname (tree);
-extern int begin_function_definition (tree, tree, tree);
extern void finish_translation_unit (void);
extern tree finish_template_type_parm (tree, tree);
extern tree finish_template_template_parm (tree, tree);
-extern tree finish_parmlist (tree, int);
extern tree begin_class_definition (tree);
extern void finish_default_args (void);
extern tree finish_member_class_template (tree);
#include "timevar.h"
#include "tree-flow.h"
-static tree grokparms (tree, tree *);
+static tree grokparms (const cp_parameter_declarator *, tree *);
static const char *redeclaration_error_message (tree, tree);
static int decl_jump_unsafe (tree);
if (TYPE_FIELDS (t))
{
- tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
- NULL);
+ tree decl = grokdeclarator (/*declarator=*/NULL,
+ declspecs, NORMAL, 0, NULL);
finish_anon_union (decl);
}
}
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
tree
-groktypename (tree typename)
+groktypename (tree type_specifiers, const cp_declarator *declarator)
{
tree specs, attrs;
tree type;
- if (TREE_CODE (typename) != TREE_LIST)
- return typename;
- split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
- type = grokdeclarator (TREE_VALUE (typename), specs,
- TYPENAME, 0, &attrs);
+ split_specs_attrs (type_specifiers, &specs, &attrs);
+ type = grokdeclarator (declarator, specs, TYPENAME, 0, &attrs);
if (attrs)
cplus_decl_attributes (&type, attrs, 0);
return type;
grokfield and not through here. */
tree
-start_decl (tree declarator,
+start_decl (const cp_declarator *declarator,
tree declspecs,
int initialized,
tree attributes,
}
pushdecl (fndecl);
- start_function (/*specs=*/NULL_TREE, fndecl, NULL_TREE, SF_PRE_PARSED);
+ start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED);
interface_unknown = old_interface_unknown;
interface_only = old_interface_only;
static_aggregates = tree_cons (init, decl, static_aggregates);
}
-/* Finish the declaration of a catch-parameter. */
-
-tree
-start_handler_parms (tree declspecs, tree declarator)
-{
- tree decl;
- if (declspecs)
- {
- decl = grokdeclarator (declarator, declspecs, CATCHPARM,
- 1, NULL);
- if (decl == NULL_TREE)
- error ("invalid catch parameter");
- }
- else
- decl = NULL_TREE;
-
- return decl;
-}
-
\f
/* Make TYPE a complete type based on INITIAL_VALUE.
Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
unqualified name, NULL_TREE is returned. */
tree
-get_scope_of_declarator (tree declarator)
+get_scope_of_declarator (const cp_declarator *declarator)
{
- if (!declarator)
- return NULL_TREE;
-
- switch (TREE_CODE (declarator))
- {
- case CALL_EXPR:
- case ARRAY_REF:
- case INDIRECT_REF:
- case ADDR_EXPR:
- /* For any of these, the main declarator is the first operand. */
- return get_scope_of_declarator (TREE_OPERAND
- (declarator, 0));
-
- case SCOPE_REF:
- /* For a pointer-to-member, continue descending. */
- if (TREE_CODE (TREE_OPERAND (declarator, 1))
- == INDIRECT_REF)
- return get_scope_of_declarator (TREE_OPERAND
- (declarator, 1));
- /* Otherwise, if the declarator-id is a SCOPE_REF, the scope in
- which the declaration occurs is the first operand. */
- return TREE_OPERAND (declarator, 0);
-
- case TREE_LIST:
- /* Attributes to be applied. The declarator is TREE_VALUE. */
- return get_scope_of_declarator (TREE_VALUE (declarator));
-
- default:
- /* Otherwise, we have a declarator-id which is not a qualified
- name; the entity will be declared in the current scope. */
- return NULL_TREE;
- }
+ while (declarator && declarator->kind != cdk_id)
+ declarator = declarator->declarator;
+
+ /* If the declarator-id is a SCOPE_REF, the scope in which the
+ declaration occurs is the first operand. */
+ if (declarator
+ && declarator->u.id.name
+ && TREE_CODE (declarator->u.id.name) == SCOPE_REF)
+ return TREE_OPERAND (declarator->u.id.name, 0);
+
+ /* Otherwise, the declarator is not a quablified name; the entity will
+ be declared in the current scope. */
+ return NULL_TREE;
}
/* Returns an ARRAY_TYPE for an array with SIZE elements of the
should not be `S'. */
tree
-grokdeclarator (tree declarator,
+grokdeclarator (const cp_declarator *declarator,
tree declspecs,
enum decl_context decl_context,
int initialized,
tree dependant_name = NULL_TREE;
tree typedef_decl = NULL_TREE;
- const char *name;
+ const char *name = NULL;
tree typedef_type = NULL_TREE;
int funcdef_flag = 0;
- enum tree_code innermost_code = ERROR_MARK;
+ cp_declarator_kind innermost_code = cdk_error;
int bitfield = 0;
#if 0
/* See the code below that used this. */
special_function_kind sfk = sfk_none;
tree dname = NULL_TREE;
- tree ctype = current_class_type;
tree ctor_return_type = NULL_TREE;
enum overload_flags flags = NO_SPECIAL;
tree quals = NULL_TREE;
tree raises = NULL_TREE;
int template_count = 0;
- tree in_namespace = NULL_TREE;
tree returned_attrs = NULL_TREE;
- tree scope = NULL_TREE;
tree parms = NULL_TREE;
+ const cp_declarator *id_declarator;
+ /* The unqualified name of the declarator; either an
+ IDENTIFIER_NODE, BIT_NOT_EXPR, or TEMPLATE_ID_EXPR. */
+ tree unqualified_id;
+ /* The class type, if any, in which this entity is located,
+ or NULL_TREE if none. Note that this value may be different from
+ the current class type; for example if an attempt is made to declare
+ "A::f" inside "B", this value will be "A". */
+ tree ctype = current_class_type;
+ /* The NAMESPACE_DECL for the namespace in which this entity is
+ located. If an unqualified name is used to declare the entity,
+ this value will be NULL_TREE, even if the entity is located at
+ namespace scope. */
+ tree in_namespace = NULL_TREE;
RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
- {
- tree *next = &declarator;
- tree decl;
- name = NULL;
-
- while (next && *next)
- {
- decl = *next;
- switch (TREE_CODE (decl))
- {
- case TREE_LIST:
- /* For attributes. */
- next = &TREE_VALUE (decl);
- break;
-
- case COND_EXPR:
- ctype = NULL_TREE;
- next = &TREE_OPERAND (decl, 0);
- break;
+ for (id_declarator = declarator;
+ id_declarator;
+ id_declarator = id_declarator->declarator)
+ {
+ if (id_declarator->kind != cdk_id)
+ innermost_code = id_declarator->kind;
- case BIT_NOT_EXPR: /* For C++ destructors! */
+ switch (id_declarator->kind)
+ {
+ case cdk_function:
+ if (id_declarator->declarator
+ && id_declarator->declarator->kind == cdk_id)
{
- tree name = TREE_OPERAND (decl, 0);
- tree rename = NULL_TREE;
-
- my_friendly_assert (flags == NO_SPECIAL, 152);
- flags = DTOR_FLAG;
- sfk = sfk_destructor;
- if (TYPE_P (name))
- TREE_OPERAND (decl, 0) = name = constructor_name (name);
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153);
- if (ctype == NULL_TREE)
- {
- if (current_class_type == NULL_TREE)
- {
- error ("destructors must be member functions");
- flags = NO_SPECIAL;
- }
- else
- {
- tree t = constructor_name (current_class_type);
- if (t != name)
- rename = t;
- }
- }
- else
- {
- tree t = constructor_name (ctype);
- if (t != name)
- rename = t;
- }
-
- if (rename)
- {
- error ("destructor `%T' must match class name `%T'",
- name, rename);
- TREE_OPERAND (decl, 0) = rename;
- }
- next = &name;
+ sfk = id_declarator->declarator->u.id.sfk;
+ if (sfk == sfk_destructor)
+ flags = DTOR_FLAG;
}
- break;
-
- case ADDR_EXPR: /* C++ reference declaration */
- /* Fall through. */
- case ARRAY_REF:
- case INDIRECT_REF:
- ctype = NULL_TREE;
- innermost_code = TREE_CODE (decl);
- next = &TREE_OPERAND (decl, 0);
- break;
-
- case CALL_EXPR:
- innermost_code = TREE_CODE (decl);
- if (decl_context == FIELD && ctype == NULL_TREE)
- ctype = current_class_type;
- if (ctype
- && TREE_OPERAND (decl, 0)
- && (TREE_CODE (TREE_OPERAND (decl, 0)) == TYPE_DECL
- && constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 0)),
- ctype)))
- TREE_OPERAND (decl, 0) = constructor_name (ctype);
- next = &TREE_OPERAND (decl, 0);
- decl = *next;
- if (ctype != NULL_TREE
- && decl != NULL_TREE && flags != DTOR_FLAG
- && constructor_name_p (decl, ctype))
- {
- sfk = sfk_constructor;
- ctor_return_type = ctype;
- }
- ctype = NULL_TREE;
- break;
-
- case TEMPLATE_ID_EXPR:
- {
- tree fns = TREE_OPERAND (decl, 0);
-
- dname = fns;
- if (TREE_CODE (dname) == COMPONENT_REF)
- dname = TREE_OPERAND (dname, 1);
- if (TREE_CODE (dname) != IDENTIFIER_NODE)
- {
- my_friendly_assert (is_overloaded_fn (dname),
- 19990331);
- dname = DECL_NAME (get_first_fn (dname));
- }
- }
- /* Fall through. */
-
- case IDENTIFIER_NODE:
- if (TREE_CODE (decl) == IDENTIFIER_NODE)
- dname = decl;
-
- next = 0;
+ break;
- if (C_IS_RESERVED_WORD (dname))
- {
- error ("declarator-id missing; using reserved word `%D'",
- dname);
- name = IDENTIFIER_POINTER (dname);
- }
- else if (!IDENTIFIER_TYPENAME_P (dname))
- name = IDENTIFIER_POINTER (dname);
- else
+ case cdk_id:
+ {
+ tree decl = id_declarator->u.id.name;
+ if (!decl)
+ break;
+ if (TREE_CODE (decl) == SCOPE_REF)
{
- my_friendly_assert (flags == NO_SPECIAL, 154);
- flags = TYPENAME_FLAG;
- ctor_return_type = TREE_TYPE (dname);
- sfk = sfk_conversion;
- if (is_typename_at_global_scope (dname))
- name = IDENTIFIER_POINTER (dname);
- else
- name = "<invalid operator>";
- }
- break;
-
- /* C++ extension */
- case SCOPE_REF:
- {
- /* Perform error checking, and decide on a ctype. */
- tree cname = TREE_OPERAND (decl, 0);
- if (cname == NULL_TREE)
- ctype = NULL_TREE;
- else if (TREE_CODE (cname) == NAMESPACE_DECL)
- {
- ctype = NULL_TREE;
- in_namespace = TREE_OPERAND (decl, 0);
- }
- else if (! is_aggr_type (cname, 1))
- ctype = NULL_TREE;
- /* Must test TREE_OPERAND (decl, 1), in case user gives
- us `typedef (class::memfunc)(int); memfunc *memfuncptr;' */
- else if (TREE_OPERAND (decl, 1)
- && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF)
- ctype = cname;
- else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM
- || TREE_CODE (cname) == BOUND_TEMPLATE_TEMPLATE_PARM)
- {
- /* This might be declaring a member of a template
- parm to be a friend. */
- ctype = cname;
- dependant_name = TREE_OPERAND (decl, 1);
- }
- else if (ctype == NULL_TREE)
- ctype = cname;
- else if (TREE_COMPLEXITY (decl) == current_class_depth)
- ;
- else
- {
- if (! UNIQUELY_DERIVED_FROM_P (cname, ctype))
- {
- error ("type `%T' is not derived from type `%T'",
- cname, ctype);
- ctype = NULL_TREE;
- }
- else
- ctype = cname;
- }
-
- /* It is valid to write:
+ tree qualifying_scope = TREE_OPERAND (decl, 0);
+;
+ /* It is valid to write:
class C { void f(); };
typedef C D;
legal; as of 2002-09-15 the committee is considering
that question. EDG 3.0 allows that syntax.
Therefore, we do as well. */
- if (ctype)
- ctype = TYPE_MAIN_VARIANT (ctype);
- /* Update the declarator so that when we process it
- again the correct type is present. */
- TREE_OPERAND (decl, 0) = ctype;
-
- if (ctype && TREE_CODE (TREE_OPERAND (decl, 1)) == TYPE_DECL
- && constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 1)),
- ctype))
- TREE_OPERAND (decl, 1) = constructor_name (ctype);
- next = &TREE_OPERAND (decl, 1);
- decl = *next;
- if (ctype)
+ if (qualifying_scope && TYPE_P (qualifying_scope))
+ {
+ ctype = TYPE_MAIN_VARIANT (qualifying_scope);
+ if (innermost_code != cdk_function
+ && current_class_type
+ && !UNIQUELY_DERIVED_FROM_P (ctype,
+ current_class_type))
+ {
+ error ("type `%T' is not derived from type `%T'",
+ ctype, current_class_type);
+ ctype = NULL_TREE;
+ }
+ TREE_OPERAND (decl, 0) = ctype;
+ }
+ else if (TREE_CODE (qualifying_scope) == NAMESPACE_DECL)
+ in_namespace = qualifying_scope;
+ decl = TREE_OPERAND (decl, 1);
+ }
+ if (TREE_CODE (decl) == BASELINK)
+ decl = BASELINK_FUNCTIONS (decl);
+ switch (TREE_CODE (decl))
+ {
+ case BIT_NOT_EXPR:
{
- tree name = decl;
+ tree type = TREE_OPERAND (decl, 0);
+ type = constructor_name (type);
+ name = IDENTIFIER_POINTER (type);
+ }
+ break;
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- name = TREE_OPERAND (name, 0);
+ case TEMPLATE_ID_EXPR:
+ {
+ tree fns = TREE_OPERAND (decl, 0);
- if (!constructor_name_p (decl, ctype))
- ;
- else if (decl == name)
- {
- sfk = sfk_constructor;
- ctor_return_type = ctype;
- }
- else
+ dname = fns;
+ if (TREE_CODE (dname) == COMPONENT_REF)
+ dname = TREE_OPERAND (dname, 1);
+ if (TREE_CODE (dname) != IDENTIFIER_NODE)
{
- sfk = sfk_destructor;
- ctor_return_type = ctype;
- flags = DTOR_FLAG;
- TREE_OPERAND (decl, 0) = constructor_name (ctype);
- next = &TREE_OPERAND (decl, 0);
+ my_friendly_assert (is_overloaded_fn (dname),
+ 19990331);
+ dname = DECL_NAME (get_first_fn (dname));
}
}
- }
- break;
+ /* Fall through. */
- case ERROR_MARK:
- next = 0;
- break;
+ case IDENTIFIER_NODE:
+ if (TREE_CODE (decl) == IDENTIFIER_NODE)
+ dname = decl;
- case TYPE_DECL:
- /* Parse error puts this typespec where
- a declarator should go. */
- error ("`%T' specified as declarator-id", DECL_NAME (decl));
- if (TREE_TYPE (decl) == current_class_type)
- error (" perhaps you want `%T' for a constructor",
- current_class_name);
- dname = DECL_NAME (decl);
- name = IDENTIFIER_POINTER (dname);
-
- /* Avoid giving two errors for this. */
- IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE;
-
- declspecs = tree_cons (NULL_TREE, integer_type_node, declspecs);
- *next = dname;
- next = 0;
+ if (C_IS_RESERVED_WORD (dname))
+ {
+ error ("declarator-id missing; using reserved word `%D'",
+ dname);
+ name = IDENTIFIER_POINTER (dname);
+ }
+ else if (!IDENTIFIER_TYPENAME_P (dname))
+ name = IDENTIFIER_POINTER (dname);
+ else
+ {
+ my_friendly_assert (flags == NO_SPECIAL, 154);
+ flags = TYPENAME_FLAG;
+ ctor_return_type = TREE_TYPE (dname);
+ sfk = sfk_conversion;
+ if (is_typename_at_global_scope (dname))
+ name = IDENTIFIER_POINTER (dname);
+ else
+ name = "<invalid operator>";
+ }
+ break;
+
+ case TYPE_DECL:
+ dname = constructor_name (TREE_TYPE (decl));
+ name = IDENTIFIER_POINTER (dname);
+ break;
+
+ default:
+ abort ();
+ }
break;
- case BASELINK:
- next = &BASELINK_FUNCTIONS (decl);
+ case cdk_array:
+ case cdk_pointer:
+ case cdk_reference:
+ case cdk_ptrmem:
break;
- case TEMPLATE_DECL:
- /* Sometimes, we see a template-name used as part of a
- decl-specifier like in
- std::allocator alloc;
- Handle that gracefully. */
- error ("invalid use of template-name '%E' in a declarator", decl);
- return error_mark_node;
+ case cdk_error:
break;
-
+
default:
- my_friendly_assert (0, 20020917);
+ abort ();
}
- }
- }
+ }
+ if (id_declarator->kind == cdk_id)
+ break;
+ }
/* A function definition's declarator must have the form of
a function declarator. */
- if (funcdef_flag && innermost_code != CALL_EXPR)
+ if (funcdef_flag && innermost_code != cdk_function)
return 0;
if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
- && innermost_code != CALL_EXPR
+ && innermost_code != cdk_function
&& ! (ctype && declspecs == NULL_TREE))
{
error ("declaration of `%D' as non-function", dname);
if (declarator)
{
/* Avoid trying to get an operand off an identifier node. */
- if (TREE_CODE (declarator) == IDENTIFIER_NODE)
- tmp = declarator;
+ if (declarator->kind != cdk_id)
+ tmp = declarator->declarator->u.id.name;
else
- tmp = TREE_OPERAND (declarator, 0);
+ tmp = declarator->u.id.name;
op = IDENTIFIER_OPNAME_P (tmp);
if (IDENTIFIER_TYPENAME_P (tmp))
{
if (nclasses > 0 && friendp)
error ("storage class specifiers invalid in friend function declarations");
- scope = get_scope_of_declarator (declarator);
-
- /* Now figure out the structure of the declarator proper.
- Descend through it, creating more complex types, until we reach
- the declared identifier (or NULL_TREE, in an abstract declarator). */
-
- while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
- && TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
+ if (!id_declarator)
+ unqualified_id = NULL_TREE;
+ else
{
- /* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
- an INDIRECT_REF (for *...),
- a CALL_EXPR (for ...(...)),
- an identifier (for the name being declared)
- or a null pointer (for the place in an absolute declarator
- where the name was omitted).
- For the last two cases, we have just exited the loop.
-
- For C++ it could also be
- a SCOPE_REF (for class :: ...). In this case, we have converted
- sensible names to types, and those are the values we use to
- qualify the member name.
- an ADDR_EXPR (for &...),
- a BIT_NOT_EXPR (for destructors)
-
- At this point, TYPE is the type of elements of an array,
- or for a function to return, or for a pointer to point to.
- After this sequence of ifs, TYPE is the type of the
- array or function or pointer, and DECLARATOR has had its
- outermost layer removed. */
-
- if (type == error_mark_node)
+ unqualified_id = id_declarator->u.id.name;
+ if (TREE_CODE (unqualified_id) == SCOPE_REF)
+ unqualified_id = TREE_OPERAND (unqualified_id, 1);
+ if (TREE_CODE (unqualified_id) == BASELINK)
+ unqualified_id = BASELINK_FUNCTIONS (unqualified_id);
+ switch (TREE_CODE (unqualified_id))
{
- if (declarator == error_mark_node)
- return error_mark_node;
- else if (TREE_CODE (declarator) == SCOPE_REF)
- declarator = TREE_OPERAND (declarator, 1);
- else
- declarator = TREE_OPERAND (declarator, 0);
- continue;
- }
- if (quals != NULL_TREE
- && (declarator == NULL_TREE
- || TREE_CODE (declarator) != SCOPE_REF))
- {
- if (ctype == NULL_TREE && TREE_CODE (type) == METHOD_TYPE)
- ctype = TYPE_METHOD_BASETYPE (type);
- if (ctype != NULL_TREE)
- {
- tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
- grok_method_quals (ctype, dummy, quals);
- type = TREE_TYPE (dummy);
- quals = NULL_TREE;
- }
- }
+ case BIT_NOT_EXPR:
+ unqualified_id
+ = constructor_name (TREE_OPERAND (unqualified_id, 0));
+ break;
+
+ case TYPE_DECL:
+ unqualified_id
+ = constructor_name (TREE_TYPE (unqualified_id));
+ break;
- switch (TREE_CODE (declarator))
- {
- case TREE_LIST:
- {
- /* We encode a declarator with embedded attributes using
- a TREE_LIST. */
- tree attrs = TREE_PURPOSE (declarator);
- tree inner_decl;
- int attr_flags;
-
- declarator = TREE_VALUE (declarator);
- inner_decl = declarator;
- while (inner_decl != NULL_TREE
- && TREE_CODE (inner_decl) == TREE_LIST)
- inner_decl = TREE_VALUE (inner_decl);
- attr_flags = 0;
- if (inner_decl == NULL_TREE
- || TREE_CODE (inner_decl) == IDENTIFIER_NODE)
- attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
- if (TREE_CODE (inner_decl) == CALL_EXPR)
- attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
- if (TREE_CODE (inner_decl) == ARRAY_REF)
- attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
- returned_attrs = decl_attributes (&type,
- chainon (returned_attrs, attrs),
- attr_flags);
- }
+ case IDENTIFIER_NODE:
+ case TEMPLATE_ID_EXPR:
break;
+
+ default:
+ abort ();
+ }
+ }
- case ARRAY_REF:
- {
- tree size = TREE_OPERAND (declarator, 1);
- declarator = TREE_OPERAND (declarator, 0);
+ /* Determine the type of the entity declared by recurring on the
+ declarator. */
+ for (;
+ declarator && declarator->kind != cdk_id;
+ declarator = declarator->declarator)
+ {
+ const cp_declarator *inner_declarator;
+ tree attrs;
- type = create_array_type_for_decl (dname, type, size);
+ if (type == error_mark_node)
+ return error_mark_node;
- if (declarator
- && (TREE_CODE (declarator) == INDIRECT_REF
- || TREE_CODE (declarator) == ADDR_EXPR))
- /* We can never complete an array type which is the target of a
- pointer, so go ahead and lay it out. */
- layout_type (type);
+ inner_declarator = declarator->declarator;
- ctype = NULL_TREE;
- }
+ attrs = declarator->attributes;
+ if (attrs)
+ {
+ int attr_flags;
+
+ attr_flags = 0;
+ if (declarator == NULL || declarator->kind == cdk_id)
+ attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
+ if (declarator->kind == cdk_function)
+ attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
+ if (declarator->kind == cdk_array)
+ attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
+ returned_attrs = decl_attributes (&type,
+ chainon (returned_attrs, attrs),
+ attr_flags);
+ }
+
+ switch (declarator->kind)
+ {
+ case cdk_array:
+ type = create_array_type_for_decl (dname, type,
+ declarator->u.array.bounds);
+ if (inner_declarator
+ && (inner_declarator->kind == cdk_pointer
+ || inner_declarator->kind == cdk_reference
+ || inner_declarator->kind == cdk_ptrmem))
+ /* We can never complete an array type which is the
+ target of a pointer, so go ahead and lay it out. */
+ layout_type (type);
break;
- case CALL_EXPR:
+ case cdk_function:
{
tree arg_types;
int funcdecl_p;
- tree inner_parms = CALL_DECLARATOR_PARMS (declarator);
- tree inner_decl = TREE_OPERAND (declarator, 0);
/* Declaring a function type.
Make sure we have a valid type for the function to return. */
type = integer_type_node;
}
- if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF)
- inner_decl = TREE_OPERAND (inner_decl, 1);
-
- if (inner_decl && TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR)
- inner_decl = dname;
-
/* Pick up type qualifiers which should be applied to `this'. */
- quals = CALL_DECLARATOR_QUALS (declarator);
+ quals = declarator->u.function.qualifiers;
/* Pick up the exception specifications. */
- raises = CALL_DECLARATOR_EXCEPTION_SPEC (declarator);
+ raises = declarator->u.function.exception_specification;
/* Say it's a definition only for the CALL_EXPR
closest to the identifier. */
- funcdecl_p
- = inner_decl
- && (TREE_CODE (inner_decl) == IDENTIFIER_NODE
- || TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR
- || TREE_CODE (inner_decl) == BIT_NOT_EXPR);
+ funcdecl_p = inner_declarator && inner_declarator->kind == cdk_id;
if (ctype == NULL_TREE
&& decl_context == FIELD
if (ctype && sfk == sfk_conversion)
TYPE_HAS_CONVERSION (ctype) = 1;
- if (ctype && constructor_name_p (dname, ctype))
+ if (ctype && (sfk == sfk_constructor
+ || sfk == sfk_destructor))
{
/* We are within a class's scope. If our declarator name
is the same as the class name, and we are defining
name);
}
- /* Construct the function type and go to the next
- inner layer of declarator. */
-
- declarator = TREE_OPERAND (declarator, 0);
-
- arg_types = grokparms (inner_parms, &parms);
+ arg_types = grokparms (declarator->u.function.parameters,
+ &parms);
- if (declarator && flags == DTOR_FLAG)
+ if (inner_declarator
+ && inner_declarator->kind == cdk_id
+ && inner_declarator->u.id.sfk == sfk_destructor
+ && arg_types != void_list_node)
{
- /* A destructor declared in the body of a class will
- be represented as a BIT_NOT_EXPR. But, we just
- want the underlying IDENTIFIER. */
- if (TREE_CODE (declarator) == BIT_NOT_EXPR)
- declarator = TREE_OPERAND (declarator, 0);
-
- if (arg_types != void_list_node)
- {
- error ("destructors may not have parameters");
- arg_types = void_list_node;
- parms = NULL_TREE;
- }
+ error ("destructors may not have parameters");
+ arg_types = void_list_node;
+ parms = NULL_TREE;
}
-
- /* ANSI says that `const int foo ();'
- does not make the function foo const. */
+
type = build_function_type (type, arg_types);
}
break;
- case ADDR_EXPR:
- case INDIRECT_REF:
+ case cdk_pointer:
+ case cdk_reference:
+ case cdk_ptrmem:
/* Filter out pointers-to-references and references-to-references.
We can get these if a TYPE_DECL is used. */
if (TREE_CODE (type) == REFERENCE_TYPE)
{
- error (TREE_CODE (declarator) == ADDR_EXPR
+ error (declarator->kind == cdk_reference
? "cannot declare reference to `%#T'"
: "cannot declare pointer to `%#T'", type);
type = TREE_TYPE (type);
}
- else if (VOID_TYPE_P (type)
- && (ctype || TREE_CODE (declarator) == ADDR_EXPR))
- error (ctype ? "cannot declare pointer to `%#T' member"
- : "cannot declare reference to `%#T'", type);
-
- /* Merge any constancy or volatility into the target type
- for the pointer. */
+ else if (VOID_TYPE_P (type))
+ {
+ if (declarator->kind == cdk_reference)
+ error ("cannot declare reference to `%#T'", type);
+ else if (declarator->kind == cdk_ptrmem)
+ error ("cannot declare pointer to `%#T' member", type);
+ }
/* We now know that the TYPE_QUALS don't apply to the decl,
but to the target of the pointer. */
type_quals = TYPE_UNQUALIFIED;
- if (TREE_CODE (declarator) == ADDR_EXPR)
+ if (declarator->kind == cdk_ptrmem
+ && (TREE_CODE (type) == FUNCTION_TYPE
+ || (quals && TREE_CODE (type) == METHOD_TYPE)))
+ {
+ tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
+ grok_method_quals (declarator->u.pointer.class_type,
+ dummy, quals);
+ type = TREE_TYPE (dummy);
+ quals = NULL_TREE;
+ }
+
+ if (declarator->kind == cdk_reference)
{
if (!VOID_TYPE_P (type))
type = build_reference_type (type);
}
else if (TREE_CODE (type) == METHOD_TYPE)
type = build_ptrmemfunc_type (build_pointer_type (type));
- else if (ctype)
- type = build_ptrmem_type (ctype, type);
+ else if (declarator->kind == cdk_ptrmem)
+ type = build_ptrmem_type (declarator->u.pointer.class_type,
+ type);
else
type = build_pointer_type (type);
/* Process a list of type modifier keywords (such as
const or volatile) that were given inside the `*' or `&'. */
- if (TREE_TYPE (declarator))
+ if (declarator->u.pointer.qualifiers)
{
tree typemodlist;
int erred = 0;
int volatilep = 0;
int restrictp = 0;
- for (typemodlist = TREE_TYPE (declarator); typemodlist;
+ for (typemodlist = declarator->u.pointer.qualifiers; typemodlist;
typemodlist = TREE_CHAIN (typemodlist))
{
tree qualifier = TREE_VALUE (typemodlist);
type = cp_build_qualified_type (type, type_quals);
type_quals = cp_type_quals (type);
}
- declarator = TREE_OPERAND (declarator, 0);
ctype = NULL_TREE;
break;
- case SCOPE_REF:
- {
- /* We have converted type names to NULL_TREE if the
- name was bogus, or to a _TYPE node, if not.
-
- The variable CTYPE holds the type we will ultimately
- resolve to. The code here just needs to build
- up appropriate member types. */
- tree sname = TREE_OPERAND (declarator, 1);
- tree t;
-
- /* Destructors can have their visibilities changed as well. */
- if (TREE_CODE (sname) == BIT_NOT_EXPR)
- sname = TREE_OPERAND (sname, 0);
-
- if (TREE_OPERAND (declarator, 0) == NULL_TREE)
- {
- /* We had a reference to a global decl, or
- perhaps we were given a non-aggregate typedef,
- in which case we cleared this out, and should just
- keep going as though it wasn't there. */
- declarator = sname;
- continue;
- }
- ctype = TREE_OPERAND (declarator, 0);
+ case cdk_error:
+ break;
- t = ctype;
- if (TREE_CODE (TREE_OPERAND (declarator, 1)) != INDIRECT_REF)
- while (t != NULL_TREE && CLASS_TYPE_P (t))
- {
- /* You're supposed to have one `template <...>'
- for every template class, but you don't need one
- for a full specialization. For example:
-
- template <class T> struct S{};
- template <> struct S<int> { void f(); };
- void S<int>::f () {}
-
- is correct; there shouldn't be a `template <>' for
- the definition of `S<int>::f'. */
- if (CLASSTYPE_TEMPLATE_INFO (t)
- && (CLASSTYPE_TEMPLATE_INSTANTIATION (t)
- || uses_template_parms (CLASSTYPE_TI_ARGS (t)))
- && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
- template_count += 1;
-
- t = TYPE_MAIN_DECL (t);
- t = DECL_CONTEXT (t);
- }
+ default:
+ abort ();
+ }
+ }
+
+ if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR
+ && TREE_CODE (type) != FUNCTION_TYPE
+ && TREE_CODE (type) != METHOD_TYPE)
+ {
+ error ("template-id `%D' used as a declarator",
+ unqualified_id);
+ unqualified_id = dname;
+ }
- if (sname == NULL_TREE)
- goto done_scoping;
+ /* If DECLARATOR is non-NULL, we know it is a cdk_id declarator;
+ otherwise, we would not have exited the loop above. */
+ if (declarator
+ && TREE_CODE (declarator->u.id.name) == SCOPE_REF
+ /* If the qualifying scope was invalid, it will have been set to
+ NULL_TREE above. */
+ && TREE_OPERAND (declarator->u.id.name, 0)
+ && TYPE_P (TREE_OPERAND (declarator->u.id.name, 0)))
+ {
+ tree t;
- if (TREE_CODE (sname) == IDENTIFIER_NODE)
- {
- /* This is the `standard' use of the scoping operator:
- basetype :: member . */
+ ctype = TREE_OPERAND (declarator->u.id.name, 0);
+ if (TYPE_P (ctype))
+ ctype = TYPE_MAIN_VARIANT (ctype);
+ t = ctype;
+ while (t != NULL_TREE && CLASS_TYPE_P (t))
+ {
+ /* You're supposed to have one `template <...>' for every
+ template class, but you don't need one for a full
+ specialization. For example:
- if (ctype == current_class_type)
- {
- /* class A {
- void A::f ();
- };
+ template <class T> struct S{};
+ template <> struct S<int> { void f(); };
+ void S<int>::f () {}
- Is this ill-formed? */
+ is correct; there shouldn't be a `template <>' for the
+ definition of `S<int>::f'. */
+ if (CLASSTYPE_TEMPLATE_INFO (t)
+ && (CLASSTYPE_TEMPLATE_INSTANTIATION (t)
+ || uses_template_parms (CLASSTYPE_TI_ARGS (t)))
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
+ template_count += 1;
- if (pedantic)
- pedwarn ("extra qualification `%T::' on member `%s' ignored",
- ctype, name);
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- if (NEW_DELETE_OPNAME_P (sname))
- /* Overloaded operator new and operator delete
- are always static functions. */
- ;
- else if (current_class_type == NULL_TREE || friendp)
- type
- = build_method_type_directly (ctype,
- TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
- else
- {
- error ("cannot declare member function `%T::%s' within `%T'",
- ctype, name, current_class_type);
- return error_mark_node;
- }
- }
- else if (RIDBIT_SETP (RID_TYPEDEF, specbits)
- || COMPLETE_TYPE_P (complete_type (ctype)))
- {
- /* Have to move this code elsewhere in this function.
- this code is used for i.e., typedef int A::M; M *pm;
-
- It is? How? jason 10/2/94 */
-
- if (current_class_type)
- {
- error ("cannot declare member `%T::%s' within `%T'",
- ctype, name, current_class_type);
- return void_type_node;
- }
- }
- else
- {
- cxx_incomplete_type_error (NULL_TREE, ctype);
- return error_mark_node;
- }
+ t = TYPE_MAIN_DECL (t);
+ t = DECL_CONTEXT (t);
+ }
- declarator = sname;
- }
- else if (TREE_CODE (sname) == SCOPE_REF)
- abort ();
- else
- {
- done_scoping:
- declarator = TREE_OPERAND (declarator, 1);
- if (declarator && TREE_CODE (declarator) == CALL_EXPR)
- /* In this case, we will deal with it later. */
- ;
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- type = build_method_type_directly (ctype,
- TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
- }
- }
- break;
+ if (ctype == current_class_type)
+ {
+ /* class A {
+ void A::f ();
+ };
- case BIT_NOT_EXPR:
- declarator = TREE_OPERAND (declarator, 0);
- break;
+ Is this ill-formed? */
- case BASELINK:
- declarator = BASELINK_FUNCTIONS (declarator);
- break;
+ if (pedantic)
+ pedwarn ("extra qualification `%T::' on member `%s' ignored",
+ ctype, name);
+ }
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ tree sname = TREE_OPERAND (declarator->u.id.name, 1);
- case RECORD_TYPE:
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- declarator = NULL_TREE;
- break;
+ if (TREE_CODE (sname) == IDENTIFIER_NODE
+ && NEW_DELETE_OPNAME_P (sname))
+ /* Overloaded operator new and operator delete
+ are always static functions. */
+ ;
+ else if (current_class_type == NULL_TREE || friendp)
+ type
+ = build_method_type_directly (ctype,
+ TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
+ else
+ {
+ error ("cannot declare member function `%T::%s' within `%T'",
+ ctype, name, current_class_type);
+ return error_mark_node;
+ }
+ }
+ else if (RIDBIT_SETP (RID_TYPEDEF, specbits)
+ || COMPLETE_TYPE_P (complete_type (ctype)))
+ {
+ /* Have to move this code elsewhere in this function.
+ this code is used for i.e., typedef int A::M; M *pm;
- case ERROR_MARK:
- declarator = NULL_TREE;
- break;
+ It is? How? jason 10/2/94 */
- default:
- abort ();
+ if (current_class_type)
+ {
+ error ("cannot declare member `%T::%s' within `%T'",
+ ctype, name, current_class_type);
+ return void_type_node;
+ }
+ }
+ else
+ {
+ cxx_incomplete_type_error (NULL_TREE, ctype);
+ return error_mark_node;
}
}
}
}
- if (declarator == NULL_TREE
- || TREE_CODE (declarator) == ERROR_MARK
- || TREE_CODE (declarator) == IDENTIFIER_NODE
- || (TREE_CODE (declarator) == TEMPLATE_ID_EXPR
- && (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)))
- /* OK */;
- else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
- {
- error ("template-id `%D' used as a declarator", declarator);
- declarator = dname;
- }
- else
- /* Unexpected declarator format. */
- abort ();
-
/* If this is declaring a typedef name, return a TYPE_DECL. */
-
if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME)
{
tree decl;
if (decl_context == FIELD)
{
- if (constructor_name_p (declarator, current_class_type))
+ if (constructor_name_p (unqualified_id, current_class_type))
pedwarn ("ISO C++ forbids nested type `%D' with same name as enclosing class",
- declarator);
- decl = build_lang_decl (TYPE_DECL, declarator, type);
+ unqualified_id);
+ decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
}
else
{
- decl = build_decl (TYPE_DECL, declarator, type);
+ decl = build_decl (TYPE_DECL, unqualified_id, type);
if (in_namespace || ctype)
error ("%Jtypedef name may not be a nested-name-specifier", decl);
if (!current_function_decl)
Nothing can refer to it, so nothing needs know about the name
change. */
if (type != error_mark_node
- && declarator
+ && unqualified_id
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& TYPE_ANONYMOUS_P (type)
tree t;
/* Replace the anonymous name with the real name everywhere. */
- lookup_tag_reverse (type, declarator);
+ lookup_tag_reverse (type, unqualified_id);
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
if (TYPE_NAME (t) == oldname)
TYPE_NAME (t) = decl;
}
if (ctype)
{
- tree dummy = build_decl (TYPE_DECL, declarator, type);
+ tree dummy = build_decl (TYPE_DECL, unqualified_id, type);
grok_method_quals (ctype, dummy, quals);
type = TREE_TYPE (dummy);
}
return type;
}
- else if (declarator == NULL_TREE && decl_context != PARM
+ else if (unqualified_id == NULL_TREE && decl_context != PARM
&& decl_context != CATCHPARM
&& TREE_CODE (type) != UNION_TYPE
&& ! bitfield)
{
error ("abstract declarator `%T' used as declaration", type);
- declarator = make_anon_name ();
+ unqualified_id = make_anon_name ();
}
/* `void' at top level (not within pointer)
if (TREE_CODE (type) == VOID_TYPE && decl_context != PARM)
{
- if (! declarator)
+ if (! unqualified_id)
error ("unnamed variable or field declared void");
- else if (TREE_CODE (declarator) == IDENTIFIER_NODE)
+ else if (TREE_CODE (unqualified_id) == IDENTIFIER_NODE)
{
- if (IDENTIFIER_OPNAME_P (declarator))
+ if (IDENTIFIER_OPNAME_P (unqualified_id))
abort ();
else
error ("variable or field `%s' declared void", name);
if (decl_context == PARM)
{
- decl = cp_build_parm_decl (declarator, type);
+ decl = cp_build_parm_decl (unqualified_id, type);
bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
/* We catch the others as conflicts with the builtin
typedefs. */
- if (friendp && declarator == ridpointers[(int) RID_SIGNED])
+ if (friendp && unqualified_id == ridpointers[(int) RID_SIGNED])
{
error ("function `%D' cannot be declared friend",
- declarator);
+ unqualified_id);
friendp = 0;
}
if (ctype == NULL_TREE)
{
error ("can't make `%D' into a method -- not in a class",
- declarator);
+ unqualified_id);
return void_type_node;
}
if (virtualp && TREE_CODE (ctype) == UNION_TYPE)
{
error ("function `%D' declared virtual inside a union",
- declarator);
+ unqualified_id);
return void_type_node;
}
- if (NEW_DELETE_OPNAME_P (declarator))
+ if (NEW_DELETE_OPNAME_P (unqualified_id))
{
if (virtualp)
{
error ("`%D' cannot be declared virtual, since it is always static",
- declarator);
+ unqualified_id);
virtualp = 0;
}
}
publicp = (! friendp || ! staticp)
&& function_context == NULL_TREE;
decl = grokfndecl (ctype, type,
- TREE_CODE (declarator) != TEMPLATE_ID_EXPR
- ? declarator : dname,
+ TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
+ ? unqualified_id : dname,
parms,
- declarator,
+ unqualified_id,
virtualp, flags, quals, raises,
friendp ? -1 : 0, friendp, publicp, inlinep,
funcdef_flag, template_count, in_namespace);
/* All method decls are public, so tell grokfndecl to set
TREE_PUBLIC, also. */
decl = grokfndecl (ctype, type,
- TREE_CODE (declarator) != TEMPLATE_ID_EXPR
- ? declarator : dname,
+ TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
+ ? unqualified_id : dname,
parms,
- declarator,
+ unqualified_id,
virtualp, flags, quals, raises,
friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
template_count, in_namespace);
&& !COMPLETE_TYPE_P (complete_type (type))
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
{
- if (declarator)
- error ("field `%D' has incomplete type", declarator);
+ if (unqualified_id)
+ error ("field `%D' has incomplete type", unqualified_id);
else
error ("name `%T' has incomplete type", type);
if (friendp)
{
error ("`%E' is neither function nor member function; "
- "cannot be declared friend", declarator);
+ "cannot be declared friend", unqualified_id);
friendp = 0;
}
decl = NULL_TREE;
if (template_class_depth (current_class_type) == 0)
{
decl = check_explicit_specialization
- (declarator, decl, template_count,
+ (unqualified_id, decl, template_count,
2 * (funcdef_flag != 0) + 4);
if (decl == error_mark_node)
return error_mark_node;
}
- decl = do_friend (ctype, declarator, decl,
+ decl = do_friend (ctype, unqualified_id, decl,
*attrlist, flags, quals, funcdef_flag);
return decl;
}
handle the initialization unless the member is
static so we make it static below. */
pedwarn ("ISO C++ forbids initialization of member `%D'",
- declarator);
- pedwarn ("making `%D' static", declarator);
+ unqualified_id);
+ pedwarn ("making `%D' static", unqualified_id);
staticp = 1;
}
if (uses_template_parms (type))
/* We'll check at instantiation time. */
;
- else if (check_static_variable_definition (declarator,
+ else if (check_static_variable_definition (unqualified_id,
type))
/* If we just return the declaration, crashes
will sometimes occur. We therefore return
{
/* C++ allows static class members. All other work
for this is done by grokfield. */
- decl = build_lang_decl (VAR_DECL, declarator, type);
+ decl = build_lang_decl (VAR_DECL, unqualified_id, type);
TREE_STATIC (decl) = 1;
/* In class context, 'static' means public access. */
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = 1;
}
else
{
- decl = build_decl (FIELD_DECL, declarator, type);
+ decl = build_decl (FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
tree original_name;
int publicp = 0;
- if (! declarator)
+ if (!unqualified_id)
return NULL_TREE;
- if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
+ if (TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR)
original_name = dname;
else
- original_name = declarator;
+ original_name = unqualified_id;
if (RIDBIT_SETP (RID_AUTO, specbits))
error ("storage class `auto' invalid for function `%s'", name);
|| RIDBIT_SETP (RID_EXTERN, specbits)
|| !RIDBIT_SETP (RID_STATIC, specbits));
- decl = grokfndecl (ctype, type, original_name, parms, declarator,
+ decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, quals, raises,
1, friendp,
publicp, inlinep, funcdef_flag,
/* It's a variable. */
/* An uninitialized decl with `extern' is a reference. */
- decl = grokvardecl (type, declarator, &specbits,
+ decl = grokvardecl (type, unqualified_id, &specbits,
initialized,
(type_quals & TYPE_QUAL_CONST) != 0,
ctype ? ctype : in_namespace);
Given the list of things declared inside the parens,
return a list of types.
- We determine whether ellipsis parms are used by PARMLIST_ELLIPSIS_P
- flag. If unset, we append void_list_node. A parmlist declared
- as `(void)' is accepted as the empty parmlist.
+ If this parameter does not end with an ellipsis, we append
+ void_list_node.
*PARMS is set to the chain of PARM_DECLs created. */
static tree
-grokparms (tree first_parm, tree *parms)
+grokparms (const cp_parameter_declarator *first_parm, tree *parms)
{
tree result = NULL_TREE;
tree decls = NULL_TREE;
- int ellipsis = !first_parm || PARMLIST_ELLIPSIS_P (first_parm);
- tree parm, chain;
+ int ellipsis = !first_parm || first_parm->ellipsis_p;
+ const cp_parameter_declarator *parm;
int any_error = 0;
- my_friendly_assert (!first_parm || TREE_PARMLIST (first_parm), 20001115);
-
- for (parm = first_parm; parm != NULL_TREE; parm = chain)
+ for (parm = first_parm; parm != NULL; parm = parm->next)
{
tree type = NULL_TREE;
- tree decl = TREE_VALUE (parm);
- tree init = TREE_PURPOSE (parm);
+ tree decl_specifiers = parm->decl_specifiers;
+ tree init = parm->default_argument;
tree specs, attrs;
+ tree decl;
- chain = TREE_CHAIN (parm);
- /* @@ weak defense against parse errors. */
- if (TREE_CODE (decl) != VOID_TYPE
- && TREE_CODE (decl) != TREE_LIST)
- {
- /* Give various messages as the need arises. */
- if (TREE_CODE (decl) == STRING_CST)
- error ("invalid string constant `%E'", decl);
- else if (TREE_CODE (decl) == INTEGER_CST)
- error ("invalid integer constant in parameter list, did you forget to give parameter name?");
- continue;
- }
-
- if (parm == void_list_node)
+ if (parm == no_parameters)
break;
- split_specs_attrs (TREE_PURPOSE (decl), &specs, &attrs);
- decl = grokdeclarator (TREE_VALUE (decl), specs,
+ split_specs_attrs (decl_specifiers, &specs, &attrs);
+ decl = grokdeclarator (parm->declarator, specs,
PARM, init != NULL_TREE, &attrs);
if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
if (VOID_TYPE_P (type))
{
if (same_type_p (type, void_type_node)
- && !DECL_NAME (decl) && !result && !chain && !ellipsis)
+ && !DECL_NAME (decl) && !result && !parm->next && !ellipsis)
/* this is a parmlist of `(void)', which is ok. */
break;
cxx_incomplete_type_error (decl, type);
This function creates a binding context for the function body
as well as setting up the FUNCTION_DECL in current_function_decl.
- Returns 1 on success. If the DECLARATOR is not suitable for a function
- (it defines a datum instead), we return 0, which tells
- yyparse to report a parse error.
-
For C++, we must first check whether that datum makes any sense.
For example, "class A local_a(1,2);" means that variable local_a
is an aggregate of type A, which should have a constructor
applied to it with the argument list [1, 2]. */
-int
-start_function (tree declspecs, tree declarator, tree attrs, int flags)
+void
+start_preparsed_function (tree decl1, tree attrs, int flags)
{
- tree decl1;
tree ctype = NULL_TREE;
tree fntype;
tree restype;
my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);
my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
- /* This should only be done once on the top most decl. */
- if (have_extern_spec)
- {
- declspecs = tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);
- have_extern_spec = false;
- }
-
- if (flags & SF_PRE_PARSED)
- {
- decl1 = declarator;
-
- fntype = TREE_TYPE (decl1);
- if (TREE_CODE (fntype) == METHOD_TYPE)
- ctype = TYPE_METHOD_BASETYPE (fntype);
-
- /* ISO C++ 11.4/5. A friend function defined in a class is in
- the (lexical) scope of the class in which it is defined. */
- if (!ctype && DECL_FRIEND_P (decl1))
- {
- ctype = DECL_FRIEND_CONTEXT (decl1);
-
- /* CTYPE could be null here if we're dealing with a template;
- for example, `inline friend float foo()' inside a template
- will have no CTYPE set. */
- if (ctype && TREE_CODE (ctype) != RECORD_TYPE)
- ctype = NULL_TREE;
- else
- doing_friend = 1;
- }
- }
- else
+ fntype = TREE_TYPE (decl1);
+ if (TREE_CODE (fntype) == METHOD_TYPE)
+ ctype = TYPE_METHOD_BASETYPE (fntype);
+
+ /* ISO C++ 11.4/5. A friend function defined in a class is in
+ the (lexical) scope of the class in which it is defined. */
+ if (!ctype && DECL_FRIEND_P (decl1))
{
- decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
- /* If the declarator is not suitable for a function definition,
- cause a syntax error. */
- if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
- return 0;
-
- cplus_decl_attributes (&decl1, attrs, 0);
-
- /* If #pragma weak was used, mark the decl weak now. */
- if (global_scope_p (current_binding_level))
- maybe_apply_pragma_weak (decl1);
-
- fntype = TREE_TYPE (decl1);
-
- restype = TREE_TYPE (fntype);
-
- if (TREE_CODE (fntype) == METHOD_TYPE)
- ctype = TYPE_METHOD_BASETYPE (fntype);
- else if (DECL_MAIN_P (decl1))
- {
- /* If this doesn't return integer_type, or a typedef to
- integer_type, complain. */
- if (!same_type_p (TREE_TYPE (TREE_TYPE (decl1)), integer_type_node))
- {
- if (pedantic || warn_return_type)
- pedwarn ("return type for `main' changed to `int'");
- TREE_TYPE (decl1) = fntype = default_function_type;
- }
- }
+ ctype = DECL_FRIEND_CONTEXT (decl1);
+
+ /* CTYPE could be null here if we're dealing with a template;
+ for example, `inline friend float foo()' inside a template
+ will have no CTYPE set. */
+ if (ctype && TREE_CODE (ctype) != RECORD_TYPE)
+ ctype = NULL_TREE;
+ else
+ doing_friend = 1;
}
if (DECL_DECLARED_INLINE_P (decl1)
start_fname_decls ();
store_parm_decls (current_function_parms);
+}
+
+
+/* Like start_preparsed_function, except that instead of a
+ FUNCTION_DECL, this function takes DECLSPECS and DECLARATOR.
+
+ Returns 1 on success. If the DECLARATOR is not suitable for a function
+ (it defines a datum instead), we return 0, which tells
+ yyparse to report a parse error. */
+
+int
+start_function (tree declspecs, const cp_declarator *declarator,
+ tree attrs)
+{
+ tree decl1;
+
+ if (have_extern_spec)
+ {
+ declspecs = tree_cons (NULL_TREE, get_identifier ("extern"),
+ declspecs);
+ /* This should only be done once on the outermost decl. */
+ have_extern_spec = false;
+ }
+
+ decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
+ /* If the declarator is not suitable for a function definition,
+ cause a syntax error. */
+ if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
+ return 0;
+
+ cplus_decl_attributes (&decl1, attrs, 0);
+
+ /* If #pragma weak was used, mark the decl weak now. */
+ if (global_scope_p (current_binding_level))
+ maybe_apply_pragma_weak (decl1);
+
+ if (DECL_MAIN_P (decl1))
+ {
+ /* If this doesn't return integer_type, or a typedef to
+ integer_type, complain. */
+ if (!same_type_p (TREE_TYPE (TREE_TYPE (decl1)), integer_type_node))
+ {
+ if (pedantic || warn_return_type)
+ pedwarn ("return type for `main' changed to `int'");
+ TREE_TYPE (decl1) = default_function_type;
+ }
+ }
+
+ start_preparsed_function (decl1, attrs, /*flags=*/SF_DEFAULT);
return 1;
}
CHANGES TO CODE IN `grokfield'. */
tree
-start_method (tree declspecs, tree declarator, tree attrlist)
+start_method (tree declspecs, const cp_declarator *declarator, tree attrlist)
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
&attrlist);
build_void_list_node (void)
{
tree t = build_tree_list (NULL_TREE, void_type_node);
- TREE_PARMLIST (t) = 1;
return t;
}
};
/* We need this in here to get the decl_context definition. */
-extern tree grokdeclarator (tree, tree, enum decl_context, int, tree*);
+extern tree grokdeclarator (const cp_declarator *, tree, enum decl_context, int, tree*);
#ifdef DEBUG_CP_BINDING_LEVELS
/* Purely for debugging purposes. */
int dup_quals = TYPE_UNQUALIFIED;
int this_quals = TYPE_UNQUALIFIED;
- do
+ while (quals)
{
int tq = cp_type_qual_from_rid (TREE_VALUE (quals));
type_quals |= tq;
quals = TREE_CHAIN (quals);
}
- while (quals);
if (dup_quals != TYPE_UNQUALIFIED)
error ("duplicate type qualifiers in %s declaration",
specs = strip_attrs (specs);
check_tag_decl (specs);
- t = groktypename (build_tree_list (specs, NULL_TREE));
+ t = groktypename (specs, /*declarator=*/NULL);
/* The only case where we need to do anything additional here is an
anonymous union field, e.g.: `struct S { union { int i; }; };'. */
CHANGES TO CODE IN `start_method'. */
tree
-grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree,
+grokfield (const cp_declarator *declarator, tree declspecs,
+ tree init, tree asmspec_tree,
tree attrlist)
{
tree value;
int flags = LOOKUP_ONLYCONVERTING;
if (declspecs == NULL_TREE
- && TREE_CODE (declarator) == SCOPE_REF
- && TREE_CODE (TREE_OPERAND (declarator, 1)) == IDENTIFIER_NODE)
+ && declarator->kind == cdk_id
+ && TREE_CODE (declarator->u.id.name) == SCOPE_REF
+ && (TREE_CODE (TREE_OPERAND (declarator->u.id.name, 1))
+ == IDENTIFIER_NODE))
{
/* Access declaration */
- if (! IS_AGGR_TYPE_CODE (TREE_CODE (TREE_OPERAND (declarator, 0))))
+ if (! IS_AGGR_TYPE_CODE (TREE_CODE
+ (TREE_OPERAND (declarator->u.id.name, 0))))
;
- else if (TREE_COMPLEXITY (declarator) == current_class_depth)
+ else if (TREE_COMPLEXITY (declarator->u.id.name) == current_class_depth)
pop_nested_class ();
- return do_class_using_decl (declarator);
+ return do_class_using_decl (declarator->u.id.name);
}
if (init
WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node. */
tree
-grokbitfield (tree declarator, tree declspecs, tree width)
+grokbitfield (const cp_declarator *declarator, tree declspecs, tree width)
{
tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL);
static tree
start_objects (int method_type, int initp)
{
- tree fnname;
tree body;
+ tree fndecl;
char type[10];
/* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */
else
sprintf (type, "%c", method_type);
- fnname = get_file_function_name_long (type);
-
- start_function (void_list_node,
- make_call_declarator (fnname, void_list_node, NULL_TREE,
- NULL_TREE),
- NULL_TREE, SF_DEFAULT);
+ fndecl = build_lang_decl (FUNCTION_DECL,
+ get_file_function_name_long (type),
+ build_function_type (void_type_node,
+ void_list_node));
+ start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
/* It can be a static function as long as collect2 does not have
to scan the object file to find its ctor/dtor routine. */
It is static because we only need to call this function from the
various constructor and destructor functions for this module. */
- start_function (/*specs=*/NULL_TREE,
- ssdf_decl,
- /*attrs=*/NULL_TREE,
- SF_PRE_PARSED);
+ start_preparsed_function (ssdf_decl,
+ /*attrs=*/NULL_TREE,
+ SF_PRE_PARSED);
/* Set up the scope of the outermost block in the function. */
body = begin_compound_stmt (BCS_FN_BODY);
PLACEMENT is the `placement' list for user-defined operator new (). */
tree
-build_new (tree placement, tree decl, tree init, int use_global_new)
+build_new (tree placement, tree type, tree nelts, tree init,
+ int use_global_new)
{
- tree type, rval;
- tree nelts = NULL_TREE, t;
- int has_array = 0;
+ tree rval;
- if (decl == error_mark_node)
+ if (type == error_mark_node)
return error_mark_node;
- if (TREE_CODE (decl) == TREE_LIST)
- {
- tree absdcl = TREE_VALUE (decl);
- tree last_absdcl = NULL_TREE;
-
- if (current_function_decl
- && DECL_CONSTRUCTOR_P (current_function_decl))
- my_friendly_assert (immediate_size_expand == 0, 19990926);
-
- nelts = integer_one_node;
-
- if (absdcl && TREE_CODE (absdcl) == CALL_EXPR)
- abort ();
- while (absdcl && TREE_CODE (absdcl) == INDIRECT_REF)
- {
- last_absdcl = absdcl;
- absdcl = TREE_OPERAND (absdcl, 0);
- }
-
- if (absdcl && TREE_CODE (absdcl) == ARRAY_REF)
- {
- /* Probably meant to be a vec new. */
- tree this_nelts;
-
- while (TREE_OPERAND (absdcl, 0)
- && TREE_CODE (TREE_OPERAND (absdcl, 0)) == ARRAY_REF)
- {
- last_absdcl = absdcl;
- absdcl = TREE_OPERAND (absdcl, 0);
- }
-
- has_array = 1;
- this_nelts = TREE_OPERAND (absdcl, 1);
- if (this_nelts != error_mark_node)
- {
- if (this_nelts == NULL_TREE)
- error ("new of array type fails to specify size");
- else if (processing_template_decl)
- {
- nelts = this_nelts;
- absdcl = TREE_OPERAND (absdcl, 0);
- }
- else
- {
- if (build_expr_type_conversion (WANT_INT | WANT_ENUM,
- this_nelts, false)
- == NULL_TREE)
- pedwarn ("size in array new must have integral type");
-
- this_nelts = save_expr (cp_convert (sizetype, this_nelts));
- absdcl = TREE_OPERAND (absdcl, 0);
- if (this_nelts == integer_zero_node)
- {
- warning ("zero size array reserves no space");
- nelts = integer_zero_node;
- }
- else
- nelts = cp_build_binary_op (MULT_EXPR, nelts, this_nelts);
- }
- }
- else
- nelts = integer_zero_node;
- }
-
- if (last_absdcl)
- TREE_OPERAND (last_absdcl, 0) = absdcl;
- else
- TREE_VALUE (decl) = absdcl;
-
- type = groktypename (decl);
- if (! type || type == error_mark_node)
- return error_mark_node;
- }
- else if (TREE_CODE (decl) == IDENTIFIER_NODE)
- {
- if (IDENTIFIER_HAS_TYPE_VALUE (decl))
- {
- /* An aggregate type. */
- type = IDENTIFIER_TYPE_VALUE (decl);
- decl = TYPE_MAIN_DECL (type);
- }
- else
- {
- /* A builtin type. */
- decl = lookup_name (decl, 1);
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 215);
- type = TREE_TYPE (decl);
- }
- }
- else if (TREE_CODE (decl) == TYPE_DECL)
- {
- type = TREE_TYPE (decl);
- }
- else
- {
- type = decl;
- decl = TYPE_MAIN_DECL (type);
- }
-
if (processing_template_decl)
{
- if (has_array)
- t = tree_cons (tree_cons (NULL_TREE, type, NULL_TREE),
- build_min_nt (ARRAY_REF, NULL_TREE, nelts,
- NULL_TREE, NULL_TREE),
- NULL_TREE);
- else
- t = type;
-
rval = build_min (NEW_EXPR, build_pointer_type (type),
- placement, t, init);
+ placement, type, nelts, init);
NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
TREE_SIDE_EFFECTS (rval) = 1;
return rval;
return error_mark_node;
}
- /* When the object being created is an array, the new-expression yields a
- pointer to the initial element (if any) of the array. For example,
- both new int and new int[10] return an int*. 5.3.4. */
- if (TREE_CODE (type) == ARRAY_TYPE && has_array == 0)
- {
- nelts = array_type_nelts_top (type);
- has_array = 1;
- type = TREE_TYPE (type);
- }
-
- if (has_array)
- t = build_nt (ARRAY_REF, type, nelts, NULL_TREE, NULL_TREE);
- else
- t = type;
-
- rval = build (NEW_EXPR, build_pointer_type (type), placement, t, init);
+ rval = build (NEW_EXPR, build_pointer_type (type), placement, type,
+ nelts, init);
NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
TREE_SIDE_EFFECTS (rval) = 1;
rval = build_new_1 (rval);
placement = TREE_OPERAND (exp, 0);
type = TREE_OPERAND (exp, 1);
- init = TREE_OPERAND (exp, 2);
+ nelts = TREE_OPERAND (exp, 2);
+ init = TREE_OPERAND (exp, 3);
globally_qualified_p = NEW_EXPR_USE_GLOBAL (exp);
- if (TREE_CODE (type) == ARRAY_REF)
+ if (nelts)
{
has_array = 1;
- nelts = outer_nelts = TREE_OPERAND (type, 1);
- type = TREE_OPERAND (type, 0);
-
+ outer_nelts = nelts;
/* Use an incomplete array type to avoid VLA headaches. */
full_type = build_cplus_array_type (type, NULL_TREE);
}
static struct impl_files *impl_file_chain;
-\f
-/* Return something to represent absolute declarators containing a *.
- TARGET is the absolute declarator that the * contains.
- CV_QUALIFIERS is a list of modifiers such as const or volatile
- to apply to the pointer type, represented as identifiers.
-
- We return an INDIRECT_REF whose "contents" are TARGET
- and whose type is the modifier list. */
-
-tree
-make_pointer_declarator (tree cv_qualifiers, tree target)
-{
- if (target && TREE_CODE (target) == IDENTIFIER_NODE
- && ANON_AGGRNAME_P (target))
- error ("type name expected before `*'");
- target = build_nt (INDIRECT_REF, target);
- TREE_TYPE (target) = cv_qualifiers;
- return target;
-}
-
-/* Return something to represent absolute declarators containing a &.
- TARGET is the absolute declarator that the & contains.
- CV_QUALIFIERS is a list of modifiers such as const or volatile
- to apply to the reference type, represented as identifiers.
-
- We return an ADDR_EXPR whose "contents" are TARGET
- and whose type is the modifier list. */
-
-tree
-make_reference_declarator (tree cv_qualifiers, tree target)
-{
- target = build_nt (ADDR_EXPR, target);
- TREE_TYPE (target) = cv_qualifiers;
- return target;
-}
-
-tree
-make_call_declarator (tree target, tree parms, tree cv_qualifiers,
- tree exception_specification)
-{
- target = build_nt (CALL_EXPR, target,
- tree_cons (parms, cv_qualifiers, NULL_TREE),
- /* The third operand is really RTL. We
- shouldn't put anything there. */
- NULL_TREE);
- CALL_DECLARATOR_EXCEPTION_SPEC (target) = exception_specification;
- return target;
-}
-
-void
-set_quals_and_spec (tree call_declarator, tree cv_qualifiers,
- tree exception_specification)
-{
- CALL_DECLARATOR_QUALS (call_declarator) = cv_qualifiers;
- CALL_DECLARATOR_EXCEPTION_SPEC (call_declarator) = exception_specification;
-}
\f
int interface_only; /* whether or not current file is only for
interface definitions. */
DECL_RESULT (thunk_fndecl) = NULL_TREE;
- start_function (NULL_TREE, thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
+ start_preparsed_function (thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
/* We don't bother with a body block for thunks. */
/* There's no need to check accessibility inside the thunk body. */
DECL_SOURCE_LOCATION (fndecl) = input_location;
interface_unknown = 1;
- start_function (NULL_TREE, fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
+ start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
clear_last_expr ();
stmt = begin_function_body ();
tree
implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
{
- tree declspecs = NULL_TREE;
- tree fn, args = NULL_TREE;
+ tree fn;
+ tree parameter_types = void_list_node;
+ tree return_type = void_type_node;
+ tree fn_type;
tree raises = empty_except_spec;
- bool retref = false;
- bool has_parm = false;
- tree name = constructor_name (type);
+ tree rhs_parm_type = NULL_TREE;
+ tree name;
switch (kind)
{
case sfk_destructor:
/* Destructor. */
- name = build_nt (BIT_NOT_EXPR, name);
- args = void_list_node;
+ name = constructor_name (type);
raises = synthesize_exception_spec (type, &locate_dtor, 0);
break;
case sfk_constructor:
/* Default constructor. */
- args = void_list_node;
+ name = constructor_name (type);
raises = synthesize_exception_spec (type, &locate_ctor, 0);
+ TYPE_HAS_CONSTRUCTOR (type) = 1;
break;
case sfk_copy_constructor:
+ TYPE_HAS_CONSTRUCTOR (type) = 1;
+ /* Fall through. */
case sfk_assignment_operator:
{
struct copy_data data;
- tree argtype = type;
- has_parm = true;
data.name = NULL;
data.quals = 0;
if (kind == sfk_assignment_operator)
{
- retref = true;
- declspecs = build_tree_list (NULL_TREE, type);
-
+ return_type = build_reference_type (type);
name = ansi_assopname (NOP_EXPR);
data.name = name;
}
+ else
+ name = constructor_name (type);
+
if (const_p)
{
data.quals = TYPE_QUAL_CONST;
- argtype = build_qualified_type (argtype, TYPE_QUAL_CONST);
+ rhs_parm_type = build_qualified_type (type, TYPE_QUAL_CONST);
}
-
- argtype = build_reference_type (argtype);
- args = build_tree_list (hash_tree_chain (argtype, NULL_TREE),
- get_identifier ("_ctor_arg"));
- args = tree_cons (NULL_TREE, args, void_list_node);
-
+ else
+ rhs_parm_type = type;
+ rhs_parm_type = build_reference_type (rhs_parm_type);
+ parameter_types = tree_cons (NULL_TREE, rhs_parm_type, parameter_types);
raises = synthesize_exception_spec (type, &locate_copy, &data);
break;
}
abort ();
}
- TREE_PARMLIST (args) = 1;
-
- {
- tree declarator = make_call_declarator (name, args, NULL_TREE, raises);
-
- if (retref)
- declarator = build_nt (ADDR_EXPR, declarator);
-
- fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE);
- if (has_parm)
- TREE_USED (FUNCTION_FIRST_USER_PARM (fn)) = 1;
- }
-
- my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 20000408);
+ /* Create the function. */
+ fn_type = build_method_type_directly (type, return_type, parameter_types);
+ if (raises)
+ fn_type = build_exception_variant (fn_type, raises);
+ fn = build_lang_decl (FUNCTION_DECL, name, fn_type);
+ if (kind == sfk_constructor || kind == sfk_copy_constructor)
+ DECL_CONSTRUCTOR_P (fn) = 1;
+ else if (kind == sfk_destructor)
+ DECL_DESTRUCTOR_P (fn) = 1;
+ else
+ {
+ DECL_ASSIGNMENT_OPERATOR_P (fn) = 1;
+ SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR);
+ }
+ /* Create the argument list. The call to "grokclassfn" will add the
+ "this" parameter and any other implicit parameters. */
+ if (rhs_parm_type)
+ {
+ /* Note that this parameter is *not* marked DECL_ARTIFICIAL; we
+ want its type to be included in the mangled function
+ name. */
+ DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type);
+ TREE_READONLY (DECL_ARGUMENTS (fn)) = 1;
+ }
+ grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL,
+ /*quals=*/NULL_TREE);
+ grok_special_member_properties (fn);
+ cp_finish_decl (fn, /*init=*/NULL_TREE, /*asmspec_tree=*/NULL_TREE,
+ /*flags=*/LOOKUP_ONLYCONVERTING);
+ DECL_IN_AGGR_P (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
DECL_NOT_REALLY_EXTERN (fn) = 1;
DECL_DECLARED_INLINE_P (fn) = 1;
/* Start processing the function. */
push_to_top_level ();
- start_function (NULL_TREE, clone, NULL_TREE, SF_PRE_PARSED);
+ start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
/* Remap the parameters. */
decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
}
\f
+/* Declarators. */
+
+/* Nothing other than the parser should be creating declarators;
+ declarators are a semi-syntactic representation of C++ entities.
+ Other parts of the front end that need to create entities (like
+ VAR_DECLs or FUNCTION_DECLs) should do that directly. */
+
+static cp_declarator *make_id_declarator
+ (tree);
+static cp_declarator *make_call_declarator
+ (cp_declarator *, cp_parameter_declarator *, tree, tree);
+static cp_declarator *make_array_declarator
+ (cp_declarator *, tree);
+static cp_declarator *make_pointer_declarator
+ (tree, cp_declarator *);
+static cp_declarator *make_reference_declarator
+ (tree, cp_declarator *);
+static cp_parameter_declarator *make_parameter_declarator
+ (tree, cp_declarator *, tree);
+static cp_declarator *make_ptrmem_declarator
+ (tree, tree, cp_declarator *);
+
+cp_declarator *cp_error_declarator;
+
+/* The obstack on which declarators and related data structures are
+ allocated. */
+static struct obstack declarator_obstack;
+
+/* Alloc BYTES from the declarator memory pool. */
+
+static inline void *
+alloc_declarator (size_t bytes)
+{
+ return obstack_alloc (&declarator_obstack, bytes);
+}
+
+/* Allocate a declarator of the indicated KIND. Clear fields that are
+ common to all declarators. */
+
+static cp_declarator *
+make_declarator (cp_declarator_kind kind)
+{
+ cp_declarator *declarator;
+
+ declarator = (cp_declarator *) alloc_declarator (sizeof (cp_declarator));
+ declarator->kind = kind;
+ declarator->attributes = NULL_TREE;
+ declarator->declarator = NULL;
+
+ return declarator;
+}
+
+/* Make a declarator for a generalized identifier. */
+
+cp_declarator *
+make_id_declarator (tree id)
+{
+ cp_declarator *declarator;
+
+ declarator = make_declarator (cdk_id);
+ declarator->u.id.name = id;
+ declarator->u.id.sfk = sfk_none;
+
+ return declarator;
+}
+
+/* Make a declarator for a pointer to TARGET. CV_QUALIFIERS is a list
+ of modifiers such as const or volatile to apply to the pointer
+ type, represented as identifiers. */
+
+cp_declarator *
+make_pointer_declarator (tree cv_qualifiers, cp_declarator *target)
+{
+ cp_declarator *declarator;
+
+ declarator = make_declarator (cdk_pointer);
+ declarator->declarator = target;
+ declarator->u.pointer.qualifiers = cv_qualifiers;
+ declarator->u.pointer.class_type = NULL_TREE;
+
+ return declarator;
+}
+
+/* Like make_pointer_declarator -- but for references. */
+
+cp_declarator *
+make_reference_declarator (tree cv_qualifiers, cp_declarator *target)
+{
+ cp_declarator *declarator;
+
+ declarator = make_declarator (cdk_reference);
+ declarator->declarator = target;
+ declarator->u.pointer.qualifiers = cv_qualifiers;
+ declarator->u.pointer.class_type = NULL_TREE;
+
+ return declarator;
+}
+
+/* Like make_pointer_declarator -- but for a pointer to a non-static
+ member of CLASS_TYPE. */
+
+cp_declarator *
+make_ptrmem_declarator (tree cv_qualifiers, tree class_type,
+ cp_declarator *pointee)
+{
+ cp_declarator *declarator;
+
+ declarator = make_declarator (cdk_ptrmem);
+ declarator->declarator = pointee;
+ declarator->u.pointer.qualifiers = cv_qualifiers;
+ declarator->u.pointer.class_type = class_type;
+
+ return declarator;
+}
+
+/* Make a declarator for the function given by TARGET, with the
+ indicated PARMS. The CV_QUALIFIERS aply to the function, as in
+ "const"-qualified member function. The EXCEPTION_SPECIFICATION
+ indicates what exceptions can be thrown. */
+
+cp_declarator *
+make_call_declarator (cp_declarator *target,
+ cp_parameter_declarator *parms,
+ tree cv_qualifiers,
+ tree exception_specification)
+{
+ cp_declarator *declarator;
+
+ declarator = make_declarator (cdk_function);
+ declarator->declarator = target;
+ declarator->u.function.parameters = parms;
+ declarator->u.function.qualifiers = cv_qualifiers;
+ declarator->u.function.exception_specification = exception_specification;
+
+ return declarator;
+}
+
+/* Make a declarator for an array of BOUNDS elements, each of which is
+ defined by ELEMENT. */
+
+cp_declarator *
+make_array_declarator (cp_declarator *element, tree bounds)
+{
+ cp_declarator *declarator;
+
+ declarator = make_declarator (cdk_array);
+ declarator->declarator = element;
+ declarator->u.array.bounds = bounds;
+
+ return declarator;
+}
+
+cp_parameter_declarator *no_parameters;
+
+/* Create a parameter declarator with the indicated DECL_SPECIFIERS,
+ DECLARATOR and DEFAULT_ARGUMENT. */
+
+cp_parameter_declarator *
+make_parameter_declarator (tree decl_specifiers,
+ cp_declarator *declarator,
+ tree default_argument)
+{
+ cp_parameter_declarator *parameter;
+
+ parameter = ((cp_parameter_declarator *)
+ alloc_declarator (sizeof (cp_parameter_declarator)));
+ parameter->next = NULL;
+ parameter->decl_specifiers = decl_specifiers;
+ parameter->declarator = declarator;
+ parameter->default_argument = default_argument;
+ parameter->ellipsis_p = false;
+
+ return parameter;
+}
+
/* The parser. */
/* Overview
static tree cp_parser_new_placement
(cp_parser *);
static tree cp_parser_new_type_id
+ (cp_parser *, tree *);
+static cp_declarator *cp_parser_new_declarator_opt
(cp_parser *);
-static tree cp_parser_new_declarator_opt
- (cp_parser *);
-static tree cp_parser_direct_new_declarator
+static cp_declarator *cp_parser_direct_new_declarator
(cp_parser *);
static tree cp_parser_new_initializer
(cp_parser *);
static tree cp_parser_init_declarator
(cp_parser *, tree, tree, bool, bool, int, bool *);
-static tree cp_parser_declarator
+static cp_declarator *cp_parser_declarator
(cp_parser *, cp_parser_declarator_kind, int *, bool *);
-static tree cp_parser_direct_declarator
+static cp_declarator *cp_parser_direct_declarator
(cp_parser *, cp_parser_declarator_kind, int *);
static enum tree_code cp_parser_ptr_operator
(cp_parser *, tree *, tree *);
(cp_parser *);
static tree cp_parser_type_specifier_seq
(cp_parser *);
-static tree cp_parser_parameter_declaration_clause
+static cp_parameter_declarator *cp_parser_parameter_declaration_clause
(cp_parser *);
-static tree cp_parser_parameter_declaration_list
- (cp_parser *);
-static tree cp_parser_parameter_declaration
+static cp_parameter_declarator *cp_parser_parameter_declaration_list
+ (cp_parser *, bool *);
+static cp_parameter_declarator *cp_parser_parameter_declaration
(cp_parser *, bool, bool *);
static void cp_parser_function_body
(cp_parser *);
(cp_parser *);
static tree cp_parser_conversion_type_id
(cp_parser *);
-static tree cp_parser_conversion_declarator_opt
+static cp_declarator *cp_parser_conversion_declarator_opt
(cp_parser *);
static bool cp_parser_ctor_initializer_opt
(cp_parser *);
static tree cp_parser_template_parameter_list
(cp_parser *);
static tree cp_parser_template_parameter
- (cp_parser *);
+ (cp_parser *, bool *);
static tree cp_parser_type_parameter
(cp_parser *);
static tree cp_parser_template_id
static tree cp_parser_maybe_treat_template_as_class
(tree, bool);
static bool cp_parser_check_declarator_template_parameters
- (cp_parser *, tree);
+ (cp_parser *, cp_declarator *);
static bool cp_parser_check_template_parameters
(cp_parser *, unsigned);
static tree cp_parser_simple_cast_expression
static bool cp_parser_constructor_declarator_p
(cp_parser *, bool);
static tree cp_parser_function_definition_from_specifiers_and_declarator
- (cp_parser *, tree, tree, tree);
+ (cp_parser *, tree, tree, const cp_declarator *);
static tree cp_parser_function_definition_after_declarator
(cp_parser *, bool);
static void cp_parser_template_declaration_after_export
static tree cp_parser_functional_cast
(cp_parser *, tree);
static tree cp_parser_save_member_function_body
- (cp_parser *, tree, tree, tree);
+ (cp_parser *, tree, cp_declarator *, tree);
static tree cp_parser_enclosed_template_argument_list
(cp_parser *);
static void cp_parser_save_default_args
static void cp_parser_check_type_definition
(cp_parser *);
static void cp_parser_check_for_definition_in_return_type
- (tree, int);
+ (cp_declarator *, int);
static void cp_parser_check_for_invalid_template_id
(cp_parser *, tree);
static bool cp_parser_non_integral_constant_expression
then an error is issued. */
static void
-cp_parser_check_for_definition_in_return_type (tree declarator,
+cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
int declares_class_or_enum)
{
/* [dcl.fct] forbids type definitions in return types.
Unfortunately, it's not easy to know whether or not we are
processing a return type until after the fact. */
while (declarator
- && (TREE_CODE (declarator) == INDIRECT_REF
- || TREE_CODE (declarator) == ADDR_EXPR))
- declarator = TREE_OPERAND (declarator, 0);
+ && (declarator->kind == cdk_pointer
+ || declarator->kind == cdk_reference
+ || declarator->kind == cdk_ptrmem))
+ declarator = declarator->declarator;
if (declarator
- && TREE_CODE (declarator) == CALL_EXPR
+ && declarator->kind == cdk_function
&& declares_class_or_enum & 2)
error ("new types may not be defined in a return type");
}
static bool
cp_parser_translation_unit (cp_parser* parser)
{
+ /* The address of the first non-permanent object on the declarator
+ obstack. */
+ static void *declarator_obstack_base;
+
+ bool success;
+
+ /* Create the declarator obstack, if necessary. */
+ if (!cp_error_declarator)
+ {
+ gcc_obstack_init (&declarator_obstack);
+ /* Create the error declarator. */
+ cp_error_declarator = make_declarator (cdk_error);
+ /* Create the empty parameter list. */
+ no_parameters = make_parameter_declarator (NULL_TREE, NULL, NULL_TREE);
+ /* Remember where the base of the declarator obstack lies. */
+ declarator_obstack_base = obstack_next_free (&declarator_obstack);
+ }
+
while (true)
{
cp_parser_declaration_seq_opt (parser);
/* If there are no tokens left then all went well. */
if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
- break;
+ {
+ /* Consume the EOF token. */
+ cp_parser_require (parser, CPP_EOF, "end-of-file");
+
+ /* Finish up. */
+ finish_translation_unit ();
- /* Otherwise, issue an error message. */
- cp_parser_error (parser, "expected declaration");
- return false;
+ success = true;
+ break;
+ }
+ else
+ {
+ cp_parser_error (parser, "expected declaration");
+ success = false;
+ break;
+ }
}
- /* Consume the EOF token. */
- cp_parser_require (parser, CPP_EOF, "end-of-file");
-
- /* Finish up. */
- finish_translation_unit ();
+ /* Make sure the declarator obstack was fully cleaned up. */
+ my_friendly_assert (obstack_next_free (&declarator_obstack) ==
+ declarator_obstack_base,
+ 20040621);
/* All went well. */
- return true;
+ return success;
}
/* Expressions [gram.expr] */
tree placement;
tree type;
tree initializer;
+ tree nelts;
/* Look for the optional `::' operator. */
global_scope_p
inform ("try removing the parentheses around the type-id");
cp_parser_direct_new_declarator (parser);
}
+ nelts = integer_one_node;
}
/* Otherwise, there must be a new-type-id. */
else
- type = cp_parser_new_type_id (parser);
+ type = cp_parser_new_type_id (parser, &nelts);
/* If the next token is a `(', then we have a new-initializer. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
return error_mark_node;
/* Create a representation of the new-expression. */
- return build_new (placement, type, initializer, global_scope_p);
+ return build_new (placement, type, nelts, initializer, global_scope_p);
}
/* Parse a new-placement.
new-type-id:
type-specifier-seq new-declarator [opt]
- Returns a TREE_LIST whose TREE_PURPOSE is the type-specifier-seq,
- and whose TREE_VALUE is the new-declarator. */
+ Returns the TYPE allocated. If the new-type-id indicates an array
+ type, *NELTS is set to the number of elements in the last array
+ bound; the TYPE will not include the last array bound. */
static tree
-cp_parser_new_type_id (cp_parser* parser)
+cp_parser_new_type_id (cp_parser* parser, tree *nelts)
{
tree type_specifier_seq;
- tree declarator;
+ cp_declarator *new_declarator;
+ cp_declarator *declarator;
+ cp_declarator *outer_declarator;
const char *saved_message;
+ tree type;
/* The type-specifier sequence must not contain type definitions.
(It cannot contain declarations of new types either, but if they
/* Restore the old message. */
parser->type_definition_forbidden_message = saved_message;
/* Parse the new-declarator. */
- declarator = cp_parser_new_declarator_opt (parser);
+ new_declarator = cp_parser_new_declarator_opt (parser);
- return build_tree_list (type_specifier_seq, declarator);
+ /* Determine the number of elements in the last array dimension, if
+ any. */
+ *nelts = NULL_TREE;
+ /* Skip down to the last array dimension. */
+ declarator = new_declarator;
+ outer_declarator = NULL;
+ while (declarator && (declarator->kind == cdk_pointer
+ || declarator->kind == cdk_ptrmem))
+ {
+ outer_declarator = declarator;
+ declarator = declarator->declarator;
+ }
+ while (declarator
+ && declarator->kind == cdk_array
+ && declarator->declarator
+ && declarator->declarator->kind == cdk_array)
+ {
+ outer_declarator = declarator;
+ declarator = declarator->declarator;
+ }
+
+ if (declarator && declarator->kind == cdk_array)
+ {
+ *nelts = declarator->u.array.bounds;
+ if (*nelts == error_mark_node)
+ *nelts = integer_one_node;
+ else if (!processing_template_decl)
+ {
+ if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, *nelts,
+ false))
+ pedwarn ("size in array new must have integral type");
+ *nelts = save_expr (cp_convert (sizetype, *nelts));
+ if (*nelts == integer_zero_node)
+ warning ("zero size array reserves no space");
+ }
+ if (outer_declarator)
+ outer_declarator->declarator = declarator->declarator;
+ else
+ new_declarator = NULL;
+ }
+
+ type = groktypename (type_specifier_seq, new_declarator);
+ if (TREE_CODE (type) == ARRAY_TYPE && *nelts == NULL_TREE)
+ {
+ *nelts = array_type_nelts_top (type);
+ type = TREE_TYPE (type);
+ }
+ return type;
}
/* Parse an (optional) new-declarator.
ptr-operator new-declarator [opt]
direct-new-declarator
- Returns a representation of the declarator. See
- cp_parser_declarator for the representations used. */
+ Returns the declarator. */
-static tree
+static cp_declarator *
cp_parser_new_declarator_opt (cp_parser* parser)
{
enum tree_code code;
/* If that worked, look for more new-declarators. */
if (cp_parser_parse_definitely (parser))
{
- tree declarator;
+ cp_declarator *declarator;
/* Parse another optional declarator. */
declarator = cp_parser_new_declarator_opt (parser);
/* Create the representation of the declarator. */
- if (code == INDIRECT_REF)
+ if (type)
+ declarator = make_ptrmem_declarator (cv_qualifier_seq,
+ type,
+ declarator);
+ else if (code == INDIRECT_REF)
declarator = make_pointer_declarator (cv_qualifier_seq,
declarator);
else
declarator = make_reference_declarator (cv_qualifier_seq,
declarator);
- /* Handle the pointer-to-member case. */
- if (type)
- declarator = build_nt (SCOPE_REF, type, declarator);
-
return declarator;
}
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
return cp_parser_direct_new_declarator (parser);
- return NULL_TREE;
+ return NULL;
}
/* Parse a direct-new-declarator.
[ expression ]
direct-new-declarator [constant-expression]
- Returns an ARRAY_REF, following the same conventions as are
- documented for cp_parser_direct_declarator. */
+ */
-static tree
+static cp_declarator *
cp_parser_direct_new_declarator (cp_parser* parser)
{
- tree declarator = NULL_TREE;
+ cp_declarator *declarator = NULL;
while (true)
{
cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
/* Add this bound to the declarator. */
- declarator = build_nt (ARRAY_REF, declarator, expression,
- NULL_TREE, NULL_TREE);
+ declarator = make_array_declarator (declarator, expression);
/* If the next token is not a `[', then there are no more
bounds. */
tree decl;
tree asm_specification;
tree attributes;
- tree declarator;
+ cp_declarator *declarator;
tree initializer = NULL_TREE;
/* Parse the declarator. */
static void
cp_parser_declaration_statement (cp_parser* parser)
{
- /* Parse the block-declaration. */
+ void *p;
+
+ /* Get the high-water mark for the DECLARATOR_OBSTACK. */
+ p = obstack_alloc (&declarator_obstack, 0);
+
+ /* Parse the block-declaration. */
cp_parser_block_declaration (parser, /*statement_p=*/true);
+ /* Free any declarators allocated. */
+ obstack_free (&declarator_obstack, p);
+
/* Finish off the statement. */
finish_stmt ();
}
cp_token token1;
cp_token token2;
int saved_pedantic;
+ void *p;
/* Set this here since we can be called after
pushing the linkage specification. */
c_lex_string_translate = 1;
+ /* Get the high-water mark for the DECLARATOR_OBSTACK. */
+ p = obstack_alloc (&declarator_obstack, 0);
+
/* If the next token is `extern' and the following token is a string
literal, then we have a linkage specification. */
if (token1.keyword == RID_EXTERN
else
/* Try to parse a block-declaration, or a function-definition. */
cp_parser_block_declaration (parser, /*statement_p=*/false);
+
+ /* Free any declarators allocated. */
+ obstack_free (&declarator_obstack, p);
}
/* Parse a block-declaration.
{
tree attributes;
tree type_specifiers;
- tree declarator;
+ cp_declarator *declarator;
/* Parse the attributes. */
attributes = cp_parser_attributes_opt (parser);
conversion-declarator:
ptr-operator conversion-declarator [opt]
- Returns a representation of the declarator. See
- cp_parser_declarator for details. */
+ */
-static tree
+static cp_declarator *
cp_parser_conversion_declarator_opt (cp_parser* parser)
{
enum tree_code code;
/* If it worked, look for more conversion-declarators. */
if (cp_parser_parse_definitely (parser))
{
- tree declarator;
-
- /* Parse another optional declarator. */
- declarator = cp_parser_conversion_declarator_opt (parser);
-
- /* Create the representation of the declarator. */
- if (code == INDIRECT_REF)
- declarator = make_pointer_declarator (cv_qualifier_seq,
+ cp_declarator *declarator;
+
+ /* Parse another optional declarator. */
+ declarator = cp_parser_conversion_declarator_opt (parser);
+
+ /* Create the representation of the declarator. */
+ if (class_type)
+ declarator = make_ptrmem_declarator (cv_qualifier_seq,
+ class_type,
declarator);
- else
- declarator = make_reference_declarator (cv_qualifier_seq,
+ else if (code == INDIRECT_REF)
+ declarator = make_pointer_declarator (cv_qualifier_seq,
+ declarator);
+ else
+ declarator = make_reference_declarator (cv_qualifier_seq,
declarator);
-
- /* Handle the pointer-to-member case. */
- if (class_type)
- declarator = build_nt (SCOPE_REF, class_type, declarator);
-
- return declarator;
+
+ return declarator;
}
- return NULL_TREE;
+ return NULL;
}
/* Parse an (optional) ctor-initializer.
{
tree parameter;
cp_token *token;
+ bool is_non_type;
/* Parse the template-parameter. */
- parameter = cp_parser_template_parameter (parser);
+ parameter = cp_parser_template_parameter (parser, &is_non_type);
/* Add it to the list. */
parameter_list = process_template_parm (parameter_list,
- parameter);
-
+ parameter,
+ is_non_type);
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
/* If it's not a `,', we're done. */
parameter-declaration
Returns a TREE_LIST. The TREE_VALUE represents the parameter. The
- TREE_PURPOSE is the default value, if any. */
+ TREE_PURPOSE is the default value, if any. *IS_NON_TYPE is set to
+ true iff this parameter is a non-type parameter. */
static tree
-cp_parser_template_parameter (cp_parser* parser)
+cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
{
cp_token *token;
+ const cp_parameter_declarator *parameter_declarator;
+ /* Assume it is a type parameter or a template parameter. */
+ *is_non_type = false;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
/* If it is `class' or `template', we have a type-parameter. */
template-parameter, the first non-nested `>' is taken as the end
of the template parameter-list rather than a greater-than
operator. */
- return
- cp_parser_parameter_declaration (parser, /*template_parm_p=*/true,
- /*parenthesized_p=*/NULL);
+ *is_non_type = true;
+ parameter_declarator
+ = cp_parser_parameter_declaration (parser, /*template_parm_p=*/true,
+ /*parenthesized_p=*/NULL);
+ return (build_tree_list
+ (parameter_declarator->default_argument,
+ grokdeclarator (parameter_declarator->declarator,
+ parameter_declarator->decl_specifiers,
+ PARM, /*initialized=*/0,
+ /*attrlist=*/NULL)));
}
/* Parse a type-parameter.
}
else
{
- tree declarator;
+ cp_declarator *declarator;
tree decl;
/* Parse the declarator. */
/*parenthesized_p=*/NULL);
cp_parser_check_for_definition_in_return_type (declarator,
declares_class_or_enum);
- if (declarator != error_mark_node)
+ if (declarator != cp_error_declarator)
{
decl = grokdeclarator (declarator, decl_specifiers,
NORMAL, 0, NULL);
bool* function_definition_p)
{
cp_token *token;
- tree declarator;
+ cp_declarator *declarator;
tree attributes;
tree asm_specification;
tree initializer;
/* If the DECLARATOR was erroneous, there's no need to go
further. */
- if (declarator == error_mark_node)
+ if (declarator == cp_error_declarator)
return error_mark_node;
cp_parser_check_for_definition_in_return_type (declarator,
attributes [opt] ptr-operator abstract-declarator [opt]
attributes [opt] direct-abstract-declarator
- Returns a representation of the declarator. If the declarator has
- the form `* declarator', then an INDIRECT_REF is returned, whose
- only operand is the sub-declarator. Analogously, `& declarator' is
- represented as an ADDR_EXPR. For `X::* declarator', a SCOPE_REF is
- used. The first operand is the TYPE for `X'. The second operand
- is an INDIRECT_REF whose operand is the sub-declarator.
-
- Otherwise, the representation is as for a direct-declarator.
-
- (It would be better to define a structure type to represent
- declarators, rather than abusing `tree' nodes to represent
- declarators. That would be much clearer and save some memory.
- There is no reason for declarators to be garbage-collected, for
- example; they are created during parser and no longer needed after
- `grokdeclarator' has been called.)
-
- For a ptr-operator that has the optional cv-qualifier-seq,
- cv-qualifiers will be stored in the TREE_TYPE of the INDIRECT_REF
- node.
-
If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to
detect constructor, destructor or conversion operators. It is set
to -1 if the declarator is a name, and +1 if it is a
If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff
the declarator is a direct-declarator of the form "(...)". */
-static tree
+static cp_declarator *
cp_parser_declarator (cp_parser* parser,
cp_parser_declarator_kind dcl_kind,
int* ctor_dtor_or_conv_p,
bool* parenthesized_p)
{
cp_token *token;
- tree declarator;
+ cp_declarator *declarator;
enum tree_code code;
tree cv_qualifier_seq;
tree class_type;
case where the dependent declarator is absent. */
if (dcl_kind != CP_PARSER_DECLARATOR_NAMED
&& !cp_parser_parse_definitely (parser))
- declarator = NULL_TREE;
+ declarator = NULL;
/* Build the representation of the ptr-operator. */
- if (code == INDIRECT_REF)
+ if (class_type)
+ declarator = make_ptrmem_declarator (cv_qualifier_seq,
+ class_type,
+ declarator);
+ else if (code == INDIRECT_REF)
declarator = make_pointer_declarator (cv_qualifier_seq,
declarator);
else
declarator = make_reference_declarator (cv_qualifier_seq,
declarator);
- /* Handle the pointer-to-member case. */
- if (class_type)
- declarator = build_nt (SCOPE_REF, class_type, declarator);
}
/* Everything else is a direct-declarator. */
else
ctor_dtor_or_conv_p);
}
- if (attributes && declarator != error_mark_node)
- declarator = tree_cons (attributes, declarator, NULL_TREE);
+ if (attributes && declarator != cp_error_declarator)
+ declarator->attributes = attributes;
return declarator;
}
CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case
of ambiguity we prefer an abstract declarator, as per
[dcl.ambig.res]. CTOR_DTOR_OR_CONV_P is as for
- cp_parser_declarator.
+ cp_parser_declarator. */
- For the declarator-id production, the representation is as for an
- id-expression, except that a qualified name is represented as a
- SCOPE_REF. A function-declarator is represented as a CALL_EXPR;
- see the documentation of the FUNCTION_DECLARATOR_* macros for
- information about how to find the various declarator components.
- An array-declarator is represented as an ARRAY_REF. The
- direct-declarator is the first operand; the constant-expression
- indicating the size of the array is the second operand. */
-
-static tree
+static cp_declarator *
cp_parser_direct_declarator (cp_parser* parser,
cp_parser_declarator_kind dcl_kind,
int* ctor_dtor_or_conv_p)
{
cp_token *token;
- tree declarator = NULL_TREE;
+ cp_declarator *declarator = NULL;
tree scope = NULL_TREE;
bool saved_default_arg_ok_p = parser->default_arg_ok_p;
bool saved_in_declarator_p = parser->in_declarator_p;
if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
{
- tree params;
+ cp_parameter_declarator *params;
unsigned saved_num_template_parameter_lists;
cp_parser_parse_tentatively (parser);
first = false;
/* Expect a `)'. */
if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
- declarator = error_mark_node;
- if (declarator == error_mark_node)
+ declarator = cp_error_declarator;
+ if (declarator == cp_error_declarator)
break;
goto handle_declarator;
/* Look for the closing `]'. */
if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"))
{
- declarator = error_mark_node;
+ declarator = cp_error_declarator;
break;
}
- declarator = build_nt (ARRAY_REF, declarator, bounds,
- NULL_TREE, NULL_TREE);
+ declarator = make_array_declarator (declarator, bounds);
}
else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
{
+ tree id;
+
/* Parse a declarator-id */
if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
cp_parser_parse_tentatively (parser);
- declarator = cp_parser_declarator_id (parser);
+ id = cp_parser_declarator_id (parser);
if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
{
if (!cp_parser_parse_definitely (parser))
- declarator = error_mark_node;
- else if (TREE_CODE (declarator) != IDENTIFIER_NODE)
+ id = error_mark_node;
+ else if (TREE_CODE (id) != IDENTIFIER_NODE)
{
cp_parser_error (parser, "expected unqualified-id");
- declarator = error_mark_node;
+ id = error_mark_node;
}
}
- if (declarator == error_mark_node)
- break;
+ if (id == error_mark_node)
+ {
+ declarator = cp_error_declarator;
+ break;
+ }
- if (TREE_CODE (declarator) == SCOPE_REF
- && !current_scope ())
+ if (TREE_CODE (id) == SCOPE_REF && !current_scope ())
{
- tree scope = TREE_OPERAND (declarator, 0);
+ tree scope = TREE_OPERAND (id, 0);
/* In the declaration of a member of a template class
outside of the class itself, the SCOPE will sometimes
TYPE_CONTEXT (scope),
TYPE_IDENTIFIER (scope));
/* Build a new DECLARATOR. */
- declarator = build_nt (SCOPE_REF,
- type,
- TREE_OPERAND (declarator, 1));
+ id = build_nt (SCOPE_REF, type, TREE_OPERAND (id, 1));
}
}
- /* Check to see whether the declarator-id names a constructor,
- destructor, or conversion. */
- if (declarator && ctor_dtor_or_conv_p
- && ((TREE_CODE (declarator) == SCOPE_REF
- && CLASS_TYPE_P (TREE_OPERAND (declarator, 0)))
- || (TREE_CODE (declarator) != SCOPE_REF
- && at_class_scope_p ())))
+ declarator = make_id_declarator (id);
+ if (id)
{
- tree unqualified_name;
tree class_type;
+ tree unqualified_name;
- /* Get the unqualified part of the name. */
- if (TREE_CODE (declarator) == SCOPE_REF)
+ if (TREE_CODE (id) == SCOPE_REF
+ && CLASS_TYPE_P (TREE_OPERAND (id, 0)))
{
- class_type = TREE_OPERAND (declarator, 0);
- unqualified_name = TREE_OPERAND (declarator, 1);
+ class_type = TREE_OPERAND (id, 0);
+ unqualified_name = TREE_OPERAND (id, 1);
}
else
{
class_type = current_class_type;
- unqualified_name = declarator;
+ unqualified_name = id;
}
- /* See if it names ctor, dtor or conv. */
- if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR
- || IDENTIFIER_TYPENAME_P (unqualified_name)
- || constructor_name_p (unqualified_name, class_type)
- || (TREE_CODE (unqualified_name) == TYPE_DECL
- && same_type_p (TREE_TYPE (unqualified_name),
- class_type)))
- *ctor_dtor_or_conv_p = -1;
- if (TREE_CODE (declarator) == SCOPE_REF
- && TREE_CODE (unqualified_name) == TYPE_DECL
- && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (unqualified_name)))
- {
- error ("invalid use of constructor as a template");
- inform ("use `%T::%D' instead of `%T::%T' to name the "
- "constructor in a qualified name", class_type,
- DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
- class_type, class_type);
- }
+ if (class_type)
+ {
+ if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
+ declarator->u.id.sfk = sfk_destructor;
+ else if (IDENTIFIER_TYPENAME_P (unqualified_name))
+ declarator->u.id.sfk = sfk_conversion;
+ else if (constructor_name_p (unqualified_name,
+ class_type)
+ || (TREE_CODE (unqualified_name) == TYPE_DECL
+ && same_type_p (TREE_TYPE (unqualified_name),
+ class_type)))
+ declarator->u.id.sfk = sfk_constructor;
+
+ if (ctor_dtor_or_conv_p && declarator->u.id.sfk != sfk_none)
+ *ctor_dtor_or_conv_p = -1;
+ if (TREE_CODE (id) == SCOPE_REF
+ && TREE_CODE (unqualified_name) == TYPE_DECL
+ && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (unqualified_name)))
+ {
+ error ("invalid use of constructor as a template");
+ inform ("use `%T::%D' instead of `%T::%T' to name the "
+ "constructor in a qualified name", class_type,
+ DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
+ class_type, class_type);
+ }
+ }
}
handle_declarator:;
pop_p = push_scope (scope);
parser->in_declarator_p = true;
if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p)
- || (declarator
- && (TREE_CODE (declarator) == SCOPE_REF
- || TREE_CODE (declarator) == IDENTIFIER_NODE)))
+ || (declarator && declarator->kind == cdk_id))
/* Default args are only allowed on function
declarations. */
parser->default_arg_ok_p = saved_default_arg_ok_p;
cp_parser_type_id (cp_parser* parser)
{
tree type_specifier_seq;
- tree abstract_declarator;
+ cp_declarator *abstract_declarator;
/* Parse the type-specifier-seq. */
type_specifier_seq
/*parenthesized_p=*/NULL);
/* Check to see if there really was a declarator. */
if (!cp_parser_parse_definitely (parser))
- abstract_declarator = NULL_TREE;
+ abstract_declarator = NULL;
- return groktypename (build_tree_list (type_specifier_seq,
- abstract_declarator));
+ return groktypename (type_specifier_seq, abstract_declarator);
}
/* Parse a type-specifier-seq.
parameter-declaration-list [opt] ... [opt]
parameter-declaration-list , ...
- Returns a representation for the parameter declarations. Each node
- is a TREE_LIST. (See cp_parser_parameter_declaration for the exact
- representation.) If the parameter-declaration-clause ends with an
- ellipsis, PARMLIST_ELLIPSIS_P will hold of the first node in the
- list. A return value of NULL_TREE indicates a
- parameter-declaration-clause consisting only of an ellipsis. */
+ Returns a representation for the parameter declarations. A return
+ value of NULL indicates a parameter-declaration-clause consisting
+ only of an ellipsis. */
-static tree
+static cp_parameter_declarator *
cp_parser_parameter_declaration_clause (cp_parser* parser)
{
- tree parameters;
+ cp_parameter_declarator *parameters;
cp_token *token;
bool ellipsis_p;
+ bool is_error;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
{
/* Consume the `...' token. */
cp_lexer_consume_token (parser->lexer);
- return NULL_TREE;
+ return NULL;
}
else if (token->type == CPP_CLOSE_PAREN)
/* There are no parameters. */
#ifndef NO_IMPLICIT_EXTERN_C
if (in_system_header && current_class_type == NULL
&& current_lang_name == lang_name_c)
- return NULL_TREE;
+ return NULL;
else
#endif
- return void_list_node;
+ return no_parameters;
}
/* Check for `(void)', too, which is a special case. */
else if (token->keyword == RID_VOID
/* Consume the `void' token. */
cp_lexer_consume_token (parser->lexer);
/* There are no parameters. */
- return void_list_node;
+ return no_parameters;
}
/* Parse the parameter-declaration-list. */
- parameters = cp_parser_parameter_declaration_list (parser);
+ parameters = cp_parser_parameter_declaration_list (parser, &is_error);
/* If a parse error occurred while parsing the
parameter-declaration-list, then the entire
parameter-declaration-clause is erroneous. */
- if (parameters == error_mark_node)
- return error_mark_node;
+ if (is_error)
+ return NULL;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
ellipsis_p = false;
/* Finish the parameter list. */
- return finish_parmlist (parameters, ellipsis_p);
+ if (parameters && ellipsis_p)
+ parameters->ellipsis_p = true;
+
+ return parameters;
}
/* Parse a parameter-declaration-list.
Returns a representation of the parameter-declaration-list, as for
cp_parser_parameter_declaration_clause. However, the
- `void_list_node' is never appended to the list. */
+ `void_list_node' is never appended to the list. Upon return,
+ *IS_ERROR will be true iff an error occurred. */
-static tree
-cp_parser_parameter_declaration_list (cp_parser* parser)
+static cp_parameter_declarator *
+cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
{
- tree parameters = NULL_TREE;
+ cp_parameter_declarator *parameters = NULL;
+ cp_parameter_declarator **tail = ¶meters;
+
+ /* Assume all will go well. */
+ *is_error = false;
/* Look for more parameters. */
while (true)
{
- tree parameter;
+ cp_parameter_declarator *parameter;
bool parenthesized_p;
/* Parse the parameter. */
parameter
/* If a parse error occurred parsing the parameter declaration,
then the entire parameter-declaration-list is erroneous. */
- if (parameter == error_mark_node)
+ if (!parameter)
{
- parameters = error_mark_node;
+ *is_error = true;
+ parameters = NULL;
break;
}
/* Add the new parameter to the list. */
- TREE_CHAIN (parameter) = parameters;
- parameters = parameter;
+ *tail = parameter;
+ tail = ¶meter->next;
/* Peek at the next token. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
}
}
- /* We built up the list in reverse order; straighten it out now. */
- return nreverse (parameters);
+ return parameters;
}
/* Parse a parameter declaration.
token encountered during the parsing of the assignment-expression
is not interpreted as a greater-than operator.)
- Returns a TREE_LIST representing the parameter-declaration. The
- TREE_PURPOSE is the default argument expression, or NULL_TREE if
- there is no default argument. The TREE_VALUE is a representation
- of the decl-specifier-seq and declarator. In particular, the
- TREE_VALUE will be a TREE_LIST whose TREE_PURPOSE represents the
- decl-specifier-seq and whose TREE_VALUE represents the declarator.
- If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff
- the declarator is of the form "(p)". */
+ Returns a representation of the parameter, or NULL if an error
+ occurs. If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to
+ true iff the declarator is of the form "(p)". */
-static tree
+static cp_parameter_declarator *
cp_parser_parameter_declaration (cp_parser *parser,
bool template_parm_p,
bool *parenthesized_p)
bool greater_than_is_operator_p;
tree decl_specifiers;
tree attributes;
- tree declarator;
+ cp_declarator *declarator;
tree default_argument;
- tree parameter;
cp_token *token;
const char *saved_message;
if (cp_parser_error_occurred (parser))
{
parser->type_definition_forbidden_message = saved_message;
- return error_mark_node;
+ return NULL;
}
/* Peek at the next token. */
|| token->type == CPP_ELLIPSIS
|| token->type == CPP_GREATER)
{
- declarator = NULL_TREE;
+ declarator = NULL;
if (parenthesized_p)
*parenthesized_p = false;
}
/* Create the representation of the parameter. */
if (attributes)
decl_specifiers = tree_cons (attributes, NULL_TREE, decl_specifiers);
- parameter = build_tree_list (default_argument,
- build_tree_list (decl_specifiers,
- declarator));
- return parameter;
+ return make_parameter_declarator (decl_specifiers,
+ declarator,
+ default_argument);
}
/* Parse a function-body.
attributes = chainon (prefix_attributes, attributes);
/* Create the bitfield declaration. */
- decl = grokbitfield (identifier,
+ decl = grokbitfield (identifier
+ ? make_id_declarator (identifier)
+ : NULL,
decl_specifiers,
width);
/* Apply the attributes. */
}
else
{
- tree declarator;
+ cp_declarator *declarator;
tree initializer;
tree asm_specification;
int ctor_dtor_or_conv_p;
/* If something went wrong parsing the declarator, make sure
that we at least consume some tokens. */
- if (declarator == error_mark_node)
+ if (declarator == cp_error_declarator)
{
/* Skip to the end of the statement. */
cp_parser_skip_to_end_of_statement (parser);
for a pure-specifier; otherwise, we look for a
constant-initializer. When we call `grokfield', it will
perform more stringent semantics checks. */
- if (TREE_CODE (declarator) == CALL_EXPR)
+ if (declarator->kind == cdk_function)
initializer = cp_parser_pure_specifier (parser);
else
/* Parse the initializer. */
static tree
cp_parser_exception_declaration (cp_parser* parser)
{
+ tree decl;
tree type_specifiers;
- tree declarator;
+ cp_declarator *declarator;
const char *saved_message;
/* If it's an ellipsis, it's easy to handle. */
type_specifiers = cp_parser_type_specifier_seq (parser);
/* If it's a `)', then there is no declarator. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
- declarator = NULL_TREE;
+ declarator = NULL;
else
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
/*ctor_dtor_or_conv_p=*/NULL,
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
- return start_handler_parms (type_specifiers, declarator);
+ if (type_specifiers)
+ {
+ decl = grokdeclarator (declarator, type_specifiers, CATCHPARM, 1, NULL);
+ if (decl == NULL_TREE)
+ error ("invalid catch parameter");
+ }
+ else
+ decl = NULL_TREE;
+
+ return decl;
}
/* Parse a throw-expression.
static bool
cp_parser_check_declarator_template_parameters (cp_parser* parser,
- tree declarator)
+ cp_declarator *declarator)
{
unsigned num_templates;
/* We haven't seen any classes that involve template parameters yet. */
num_templates = 0;
- switch (TREE_CODE (declarator))
+ switch (declarator->kind)
{
- case CALL_EXPR:
- case ARRAY_REF:
- case INDIRECT_REF:
- case ADDR_EXPR:
- {
- tree main_declarator = TREE_OPERAND (declarator, 0);
- return
- cp_parser_check_declarator_template_parameters (parser,
- main_declarator);
- }
-
- case SCOPE_REF:
- {
- tree scope;
- tree member;
-
- scope = TREE_OPERAND (declarator, 0);
- member = TREE_OPERAND (declarator, 1);
-
- /* If this is a pointer-to-member, then we are not interested
- in the SCOPE, because it does not qualify the thing that is
- being declared. */
- if (TREE_CODE (member) == INDIRECT_REF)
- return (cp_parser_check_declarator_template_parameters
- (parser, member));
-
- while (scope && CLASS_TYPE_P (scope))
- {
- /* You're supposed to have one `template <...>'
- for every template class, but you don't need one
- for a full specialization. For example:
-
- template <class T> struct S{};
- template <> struct S<int> { void f(); };
- void S<int>::f () {}
-
- is correct; there shouldn't be a `template <>' for
- the definition of `S<int>::f'. */
- if (CLASSTYPE_TEMPLATE_INFO (scope)
- && (CLASSTYPE_TEMPLATE_INSTANTIATION (scope)
- || uses_template_parms (CLASSTYPE_TI_ARGS (scope)))
- && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)))
- ++num_templates;
+ case cdk_id:
+ if (TREE_CODE (declarator->u.id.name) == SCOPE_REF)
+ {
+ tree scope;
+ tree member;
- scope = TYPE_CONTEXT (scope);
- }
- }
+ scope = TREE_OPERAND (declarator->u.id.name, 0);
+ member = TREE_OPERAND (declarator->u.id.name, 1);
- /* Fall through. */
+ while (scope && CLASS_TYPE_P (scope))
+ {
+ /* You're supposed to have one `template <...>'
+ for every template class, but you don't need one
+ for a full specialization. For example:
+
+ template <class T> struct S{};
+ template <> struct S<int> { void f(); };
+ void S<int>::f () {}
+
+ is correct; there shouldn't be a `template <>' for
+ the definition of `S<int>::f'. */
+ if (CLASSTYPE_TEMPLATE_INFO (scope)
+ && (CLASSTYPE_TEMPLATE_INSTANTIATION (scope)
+ || uses_template_parms (CLASSTYPE_TI_ARGS (scope)))
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)))
+ ++num_templates;
+
+ scope = TYPE_CONTEXT (scope);
+ }
+ }
- default:
/* If the DECLARATOR has the form `X<y>' then it uses one
additional level of template parameters. */
- if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
+ if (TREE_CODE (declarator->u.id.name) == TEMPLATE_ID_EXPR)
++num_templates;
return cp_parser_check_template_parameters (parser,
num_templates);
+
+ case cdk_function:
+ case cdk_array:
+ case cdk_pointer:
+ case cdk_reference:
+ case cdk_ptrmem:
+ return (cp_parser_check_declarator_template_parameters
+ (parser, declarator->declarator));
+
+ case cdk_error:
+ return true;
+
+ default:
+ abort ();
+ return false;
}
}
(cp_parser* parser,
tree decl_specifiers,
tree attributes,
- tree declarator)
+ const cp_declarator *declarator)
{
tree fn;
bool success_p;
/* Begin the function-definition. */
- success_p = begin_function_definition (decl_specifiers,
- attributes,
- declarator);
+ success_p = start_function (decl_specifiers, declarator, attributes);
+
+ /* The things we're about to see are not directly qualified by any
+ template headers we've seen thus far. */
+ reset_specialization ();
/* If there were names looked up in the decl-specifier-seq that we
did not check, check them now. We must wait until we are in the
if (!success_p)
{
- /* If begin_function_definition didn't like the definition, skip
- the entire function. */
+ /* Skip the entire function. */
error ("invalid function declaration");
cp_parser_skip_to_end_of_block_or_statement (parser);
fn = error_mark_node;
static tree
cp_parser_save_member_function_body (cp_parser* parser,
tree decl_specifiers,
- tree declarator,
+ cp_declarator *declarator,
tree attributes)
{
cp_token_cache *cache;
/* Let the front end know that we going to be defining this
function. */
- start_function (NULL_TREE, member_function, NULL_TREE,
- SF_PRE_PARSED | SF_INCLASS_INLINE);
+ start_preparsed_function (member_function, NULL_TREE,
+ SF_PRE_PARSED | SF_INCLASS_INLINE);
/* Now, parse the body of the function. */
cp_parser_function_definition_after_declarator (parser,
type);
/* Call grokdeclarator to figure out what type this is. */
- expr = grokdeclarator (NULL_TREE,
+ expr = grokdeclarator (NULL,
type,
TYPENAME,
/*initialized=*/0,
}
/* Process information from new template parameter NEXT and append it to the
- LIST being built. */
+ LIST being built. This new parameter is a non-type parameter iff
+ IS_NON_TYPE is true. */
tree
-process_template_parm (tree list, tree next)
+process_template_parm (tree list, tree next, bool is_non_type)
{
tree parm;
tree decl = 0;
tree defval;
- int is_type, idx;
+ int idx;
parm = next;
my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259);
defval = TREE_PURPOSE (parm);
- parm = TREE_VALUE (parm);
- is_type = TREE_PURPOSE (parm) == class_type_node;
if (list)
{
else
idx = 0;
- if (!is_type)
+ if (is_non_type)
{
- my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
- /* is a const-param */
- parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
- PARM, 0, NULL);
+ parm = TREE_VALUE (parm);
+
SET_DECL_TEMPLATE_PARM_P (parm);
/* [temp.param]
else
{
tree t;
- parm = TREE_VALUE (parm);
+ parm = TREE_VALUE (TREE_VALUE (parm));
if (parm && TREE_CODE (parm) == TEMPLATE_DECL)
{
}
}
else
- val = groktypename (arg);
+ val = arg;
}
else
{
doesn't check TREE_PARMLIST. */
new_parms = tree_cons (defarg, type, new_parms);
- /* And note that these are parameters. */
- TREE_PARMLIST (new_parms) = 1;
-
return new_parms;
}
case TREE_LIST:
{
- tree purpose, value, chain, result;
+ tree purpose, value, chain;
if (t == void_list_node)
return t;
&& value == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
return t;
- if (TREE_PARMLIST (t))
- {
- result = tree_cons (purpose, value, chain);
- TREE_PARMLIST (result) = 1;
- }
- else
- result = hash_tree_cons (purpose, value, chain);
- return result;
+ return hash_tree_cons (purpose, value, chain);
}
case TREE_VEC:
if (type != NULL_TREE)
}
case INDIRECT_REF:
- {
- tree e = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
- if (e == error_mark_node)
- return error_mark_node;
- return make_pointer_declarator (type, e);
- }
-
case ADDR_EXPR:
- {
- tree e = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
- if (e == error_mark_node)
- return error_mark_node;
- return make_reference_declarator (type, e);
- }
+ case CALL_EXPR:
+ abort ();
case ARRAY_REF:
{
return build_nt (ARRAY_REF, e1, e2, NULL_TREE, NULL_TREE);
}
- case CALL_EXPR:
- {
- tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
- tree e2 = (tsubst_call_declarator_parms
- (CALL_DECLARATOR_PARMS (t), args, complain, in_decl));
- tree e3 = tsubst (CALL_DECLARATOR_EXCEPTION_SPEC (t), args,
- complain, in_decl);
-
- if (e1 == error_mark_node || e2 == error_mark_node
- || e3 == error_mark_node)
- return error_mark_node;
-
- return make_call_declarator (e1, e2, CALL_DECLARATOR_QUALS (t), e3);
- }
-
case SCOPE_REF:
{
tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
(RECUR (TREE_OPERAND (t, 0)),
RECUR (TREE_OPERAND (t, 1)),
RECUR (TREE_OPERAND (t, 2)),
+ RECUR (TREE_OPERAND (t, 3)),
NEW_EXPR_USE_GLOBAL (t));
case DELETE_EXPR:
/* Set up context. */
import_export_decl (d);
- start_function (NULL_TREE, d, NULL_TREE, SF_PRE_PARSED);
+ start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
/* Create substitution entries for the parameters. */
subst_decl = DECL_TEMPLATE_RESULT (template_for_substitution (d));
return decl;
}
-/* Begin a function definition declared with DECL_SPECS, ATTRIBUTES,
- and DECLARATOR. Returns nonzero if the function-declaration is
- valid. */
-
-int
-begin_function_definition (tree decl_specs, tree attributes, tree declarator)
-{
- if (!start_function (decl_specs, declarator, attributes, SF_DEFAULT))
- return 0;
-
- /* The things we're about to see are not directly qualified by any
- template headers we've seen thus far. */
- reset_specialization ();
-
- return 1;
-}
-
/* Finish a translation unit. */
void
return argument;
}
-/* Finish a parameter list, indicated by PARMS. If ELLIPSIS is
- nonzero, the parameter list was terminated by a `...'. */
-
-tree
-finish_parmlist (tree parms, int ellipsis)
-{
- if (parms)
- {
- /* We mark the PARMS as a parmlist so that declarator processing can
- disambiguate certain constructs. */
- TREE_PARMLIST (parms) = 1;
- /* We do not append void_list_node here, but leave it to grokparms
- to do that. */
- PARMLIST_ELLIPSIS_P (parms) = ellipsis;
- }
- return parms;
-}
-
/* Begin a class definition, as indicated by T. */
tree