static int enum_overflow;
-/* These #defines are for clarity in working with the information block
- returned by get_parm_info. */
-#define ARG_INFO_PARMS(args) TREE_PURPOSE(args)
-#define ARG_INFO_TAGS(args) TREE_VALUE(args)
-#define ARG_INFO_TYPES(args) TREE_CHAIN(args)
-#define ARG_INFO_OTHERS(args) TREE_TYPE(args)
-
/* The file and line that the prototype came from if this is an
old-style definition; used for diagnostics in
store_parm_decls_oldstyle. */
/* The argument information structure for the function currently being
defined. */
-static GTY(()) tree current_function_arg_info;
+static struct c_arg_info *current_function_arg_info;
/* The obstack on which parser and related data structures, which are
not live beyond their top-level declaration or definition, are
/* Forward declarations. */
static tree lookup_name_in_scope (tree, struct c_scope *);
static tree c_make_fname_decl (tree, int);
-static tree grokdeclarator (tree, tree, enum decl_context, bool, tree *);
-static tree grokparms (tree, bool);
+static tree grokdeclarator (const struct c_declarator *, tree,
+ enum decl_context, bool, tree *);
+static tree grokparms (struct c_arg_info *, bool);
static void layout_array_type (tree);
\f
/* States indicating how grokdeclarator() should handle declspecs marked
true if "static" is inside the [], false otherwise. VLA_UNSPEC_P
is true if the array is [*], a VLA of unspecified length which is
nevertheless a complete type (not currently implemented by GCC),
- false otherwise. The declarator is constructed as an ARRAY_REF
- (to be decoded by grokdeclarator), whose operand 0 is what's on the
- left of the [] (filled by in set_array_declarator_inner) and operand 1
- is the expression inside; whose TREE_TYPE is the type qualifiers and
- which has TREE_STATIC set if "static" is used. */
+ false otherwise. The field for the contained declarator is left to be
+ filled in by set_array_declarator_inner. */
-tree
+struct c_declarator *
build_array_declarator (tree expr, tree quals, bool static_p,
bool vla_unspec_p)
{
- tree decl;
- decl = build_nt (ARRAY_REF, NULL_TREE, expr, NULL_TREE, NULL_TREE);
- TREE_TYPE (decl) = quals;
- TREE_STATIC (decl) = (static_p ? 1 : 0);
+ struct c_declarator *declarator = XOBNEW (&parser_obstack,
+ struct c_declarator);
+ declarator->kind = cdk_array;
+ declarator->declarator = 0;
+ declarator->u.array.dimen = expr;
+ declarator->u.array.quals = quals;
+ declarator->u.array.static_p = static_p;
+ declarator->u.array.vla_unspec_p = vla_unspec_p;
if (pedantic && !flag_isoc99)
{
if (static_p || quals != NULL_TREE)
}
if (vla_unspec_p)
warning ("GCC does not yet properly implement `[*]' array declarators");
- return decl;
+ return declarator;
}
-/* Set the type of an array declarator. DECL is the declarator, as
- constructed by build_array_declarator; TYPE is what appears on the left
- of the [] and goes in operand 0. ABSTRACT_P is true if it is an
- abstract declarator, false otherwise; this is used to reject static and
- type qualifiers in abstract declarators, where they are not in the
- C99 grammar. */
+/* Set the contained declarator of an array declarator. DECL is the
+ declarator, as constructed by build_array_declarator; INNER is what
+ appears on the left of the []. ABSTRACT_P is true if it is an
+ abstract declarator, false otherwise; this is used to reject static
+ and type qualifiers in abstract declarators, where they are not in
+ the C99 grammar (subject to possible change in DR#289). */
-tree
-set_array_declarator_inner (tree decl, tree type, bool abstract_p)
+struct c_declarator *
+set_array_declarator_inner (struct c_declarator *decl,
+ struct c_declarator *inner, bool abstract_p)
{
- TREE_OPERAND (decl, 0) = type;
- if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
+ decl->declarator = inner;
+ if (abstract_p && (decl->u.array.quals != NULL_TREE
+ || decl->u.array.static_p))
error ("static or type qualifiers in abstract declarator");
return decl;
}
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
tree
-groktypename (tree type_name)
+groktypename (struct c_type_name *type_name)
{
+ tree type;
tree specs, attrs;
- if (TREE_CODE (type_name) != TREE_LIST)
- return type_name;
+ split_specs_attrs (type_name->specs, &specs, &attrs);
- split_specs_attrs (TREE_PURPOSE (type_name), &specs, &attrs);
-
- type_name = grokdeclarator (TREE_VALUE (type_name), specs, TYPENAME, false,
- NULL);
+ type = grokdeclarator (type_name->declarator, specs, TYPENAME, false,
+ NULL);
/* Apply attributes. */
- decl_attributes (&type_name, attrs, 0);
+ decl_attributes (&type, attrs, 0);
- return type_name;
+ return type;
}
/* Decode a declarator in an ordinary declaration or data definition.
grokfield and not through here. */
tree
-start_decl (tree declarator, tree declspecs, bool initialized, tree attributes)
+start_decl (struct c_declarator *declarator, tree declspecs,
+ bool initialized, tree attributes)
{
tree decl;
tree tem;
if (TREE_CODE (decl) == FUNCTION_DECL
&& targetm.calls.promote_prototypes (TREE_TYPE (decl)))
{
- tree ce = declarator;
+ struct c_declarator *ce = declarator;
- if (TREE_CODE (ce) == INDIRECT_REF)
- ce = TREE_OPERAND (declarator, 0);
- if (TREE_CODE (ce) == CALL_EXPR)
+ if (ce->kind == cdk_pointer)
+ ce = declarator->declarator;
+ if (ce->kind == cdk_function)
{
- tree args = TREE_PURPOSE (TREE_OPERAND (ce, 1));
+ tree args = ce->u.arg_info->parms;
for (; args; args = TREE_CHAIN (args))
{
tree type = TREE_TYPE (args);
/* Given a parsed parameter declaration, decode it into a PARM_DECL. */
tree
-grokparm (tree parm)
+grokparm (const struct c_parm *parm)
{
- tree decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
- TREE_PURPOSE (TREE_PURPOSE (parm)),
- PARM, false, NULL);
+ tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
+ NULL);
- decl_attributes (&decl, TREE_VALUE (parm), 0);
+ decl_attributes (&decl, parm->attrs, 0);
return decl;
}
and push that on the current scope. */
void
-push_parm_decl (tree parm)
+push_parm_decl (const struct c_parm *parm)
{
tree decl;
- decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
- TREE_PURPOSE (TREE_PURPOSE (parm)),
- PARM, false, NULL);
- decl_attributes (&decl, TREE_VALUE (parm), 0);
+ decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL);
+ decl_attributes (&decl, parm->attrs, 0);
decl = pushdecl (decl);
and `extern' are interpreted. */
static tree
-grokdeclarator (tree declarator, tree declspecs,
+grokdeclarator (const struct c_declarator *declarator, tree declspecs,
enum decl_context decl_context, bool initialized, tree *width)
{
int specbits = 0;
const char *name, *orig_name;
tree typedef_type = 0;
int funcdef_flag = 0;
- enum tree_code innermost_code = ERROR_MARK;
+ bool funcdef_syntax = false;
int size_varies = 0;
tree decl_attr = NULL_TREE;
tree array_ptr_quals = NULL_TREE;
tree returned_attrs = NULL_TREE;
bool bitfield = width != NULL;
tree element_type;
- tree arg_info = NULL_TREE;
+ struct c_arg_info *arg_info = 0;
if (decl_context == FUNCDEF)
funcdef_flag = 1, decl_context = NORMAL;
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
{
- tree decl = declarator;
+ const struct c_declarator *decl = declarator;
name = 0;
while (decl)
- switch (TREE_CODE (decl))
+ switch (decl->kind)
{
- case ARRAY_REF:
- case INDIRECT_REF:
- case CALL_EXPR:
- innermost_code = TREE_CODE (decl);
- decl = TREE_OPERAND (decl, 0);
+ case cdk_function:
+ case cdk_array:
+ case cdk_pointer:
+ funcdef_syntax = (decl->kind == cdk_function);
+ decl = decl->declarator;
break;
- case TREE_LIST:
- decl = TREE_VALUE (decl);
+ case cdk_attrs:
+ decl = decl->declarator;
break;
- case IDENTIFIER_NODE:
- name = IDENTIFIER_POINTER (decl);
+ case cdk_id:
+ if (decl->u.id)
+ name = IDENTIFIER_POINTER (decl->u.id);
decl = 0;
break;
/* A function definition's declarator must have the form of
a function declarator. */
- if (funcdef_flag && innermost_code != CALL_EXPR)
+ if (funcdef_flag && !funcdef_syntax)
return 0;
/* If this looks like a function definition, make it one,
Descend through it, creating more complex types, until we reach
the declared identifier (or NULL_TREE, in an absolute declarator). */
- while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE)
+ while (declarator && declarator->kind != cdk_id)
{
if (type == error_mark_node)
{
- declarator = TREE_OPERAND (declarator, 0);
+ declarator = declarator->declarator;
continue;
}
- /* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
- an INDIRECT_REF (for *...),
- a CALL_EXPR (for ...(...)),
- a TREE_LIST (for nested attributes),
- an identifier (for the name being declared)
- or a null pointer (for the place in an absolute declarator
+ /* Each level of DECLARATOR is either a cdk_array (for ...[..]),
+ a cdk_pointer (for *...),
+ a cdk_function (for ...(...)),
+ a cdk_attrs (for nested attributes),
+ or a cdk_id (for the name being declared
+ or the place in an absolute declarator
where the name was omitted).
- For the last two cases, we have just exited the loop.
+ For the last case, we have just exited the loop.
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.
array_parm_static = 0;
}
- switch (TREE_CODE (declarator))
+ switch (declarator->kind)
{
- case TREE_LIST:
+ case cdk_attrs:
{
- /* We encode a declarator with embedded attributes using a
- TREE_LIST. */
- tree attrs = TREE_PURPOSE (declarator);
- tree inner_decl;
+ /* A declarator with embedded attributes. */
+ tree attrs = declarator->u.attrs;
+ const struct c_declarator *inner_decl;
int attr_flags = 0;
- declarator = TREE_VALUE (declarator);
+ declarator = declarator->declarator;
inner_decl = declarator;
- while (inner_decl != NULL_TREE
- && TREE_CODE (inner_decl) == TREE_LIST)
- inner_decl = TREE_VALUE (inner_decl);
- if (inner_decl == NULL_TREE
- || TREE_CODE (inner_decl) == IDENTIFIER_NODE)
+ while (inner_decl->kind == cdk_attrs)
+ inner_decl = inner_decl->declarator;
+ if (inner_decl->kind == cdk_id)
attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
- else if (TREE_CODE (inner_decl) == CALL_EXPR)
+ else if (inner_decl->kind == cdk_function)
attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
- else if (TREE_CODE (inner_decl) == ARRAY_REF)
+ else if (inner_decl->kind == cdk_array)
attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
returned_attrs = decl_attributes (&type,
chainon (returned_attrs, attrs),
attr_flags);
break;
}
- case ARRAY_REF:
+ case cdk_array:
{
tree itype = NULL_TREE;
- tree size = TREE_OPERAND (declarator, 1);
+ tree size = declarator->u.array.dimen;
/* The index is a signed object `sizetype' bits wide. */
tree index_type = c_common_signed_type (sizetype);
- array_ptr_quals = TREE_TYPE (declarator);
- array_parm_static = TREE_STATIC (declarator);
+ array_ptr_quals = declarator->u.array.quals;
+ array_parm_static = declarator->u.array.static_p;
- declarator = TREE_OPERAND (declarator, 0);
+ declarator = declarator->declarator;
/* Check for some types that there cannot be arrays of. */
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
}
- else if (declarator && TREE_CODE (declarator) == INDIRECT_REF)
+ else if (declarator->kind == cdk_pointer)
/* 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:
{
/* Say it's a definition only for the declarator closest
to the identifier, apart possibly from some
tree arg_types;
if (funcdef_flag)
{
- tree t = TREE_OPERAND (declarator, 0);
- while (TREE_CODE (t) == TREE_LIST)
- t = TREE_VALUE (t);
- really_funcdef = (TREE_CODE (t) == IDENTIFIER_NODE);
+ const struct c_declarator *t = declarator->declarator;
+ while (t->kind == cdk_attrs)
+ t = t->declarator;
+ really_funcdef = (t->kind == cdk_id);
}
/* Declaring a function type. Make sure we have a valid
/* Construct the function type and go to the next
inner layer of declarator. */
- arg_info = TREE_OPERAND (declarator, 1);
+ arg_info = declarator->u.arg_info;
arg_types = grokparms (arg_info, really_funcdef);
/* Type qualifiers before the return type of the function
type_quals = TYPE_UNQUALIFIED;
type = build_function_type (type, arg_types);
- declarator = TREE_OPERAND (declarator, 0);
+ declarator = declarator->declarator;
/* Set the TYPE_CONTEXTs for each tagged type which is local to
the formal parameter list of this FUNCTION_TYPE to point to
{
tree link;
- for (link = ARG_INFO_TAGS (arg_info);
+ for (link = arg_info->tags;
link;
link = TREE_CHAIN (link))
TYPE_CONTEXT (TREE_VALUE (link)) = type;
}
break;
}
- case INDIRECT_REF:
+ case cdk_pointer:
{
/* Merge any constancy or volatility into the target type
for the pointer. */
/* Process a list of type modifier keywords (such as const
or volatile) that were given inside the `*'. */
- if (TREE_TYPE (declarator))
+ if (declarator->u.pointer_quals)
{
tree typemodlist;
int erred = 0;
constp = 0;
volatilep = 0;
restrictp = 0;
- for (typemodlist = TREE_TYPE (declarator); typemodlist;
+ for (typemodlist = declarator->u.pointer_quals; typemodlist;
typemodlist = TREE_CHAIN (typemodlist))
{
tree qualifier = TREE_VALUE (typemodlist);
| (volatilep ? TYPE_QUAL_VOLATILE : 0));
}
- declarator = TREE_OPERAND (declarator, 0);
+ declarator = declarator->declarator;
break;
}
default:
pedwarn ("ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
- decl = build_decl (TYPE_DECL, declarator, type);
+ decl = build_decl (TYPE_DECL, declarator->u.id, type);
if ((specbits & (1 << (int) RID_SIGNED))
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
type_as_written = type;
- decl = build_decl (PARM_DECL, declarator, type);
+ decl = build_decl (PARM_DECL, declarator->u.id, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
type_quals),
TYPE_DOMAIN (type));
- decl = build_decl (FIELD_DECL, declarator, type);
+ decl = build_decl (FIELD_DECL, declarator->u.id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (size_varies)
error ("invalid storage class for function `%s'", name);
}
- decl = build_decl (FUNCTION_DECL, declarator, type);
+ decl = build_decl (FUNCTION_DECL, declarator->u.id, type);
decl = build_decl_attribute_variant (decl, decl_attr);
DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
C_FUNCTION_IMPLICIT_INT (decl) = 1;
/* Record presence of `inline', if it is reasonable. */
- if (MAIN_NAME_P (declarator))
+ if (MAIN_NAME_P (declarator->u.id))
{
if (inlinep)
warning ("cannot inline function `main'");
the 'extern' declaration is taken to refer to that decl.) */
if (extern_ref && current_scope != file_scope)
{
- tree global_decl = identifier_global_value (declarator);
- tree visible_decl = lookup_name (declarator);
+ tree global_decl = identifier_global_value (declarator->u.id);
+ tree visible_decl = lookup_name (declarator->u.id);
if (global_decl
&& global_decl != visible_decl
"'extern'");
}
- decl = build_decl (VAR_DECL, declarator, type);
+ decl = build_decl (VAR_DECL, declarator->u.id, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
when FUNCDEF_FLAG is false. */
static tree
-grokparms (tree arg_info, bool funcdef_flag)
+grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
{
- tree arg_types = ARG_INFO_TYPES (arg_info);
+ tree arg_types = arg_info->types;
if (warn_strict_prototypes && arg_types == 0 && !funcdef_flag
&& !in_system_header)
if (! funcdef_flag)
pedwarn ("parameter names (without types) in function declaration");
- ARG_INFO_PARMS (arg_info) = ARG_INFO_TYPES (arg_info);
- ARG_INFO_TYPES (arg_info) = 0;
+ arg_info->parms = arg_info->types;
+ arg_info->types = 0;
return 0;
}
else
the scope of the declaration, so the types can never be
completed, and no call can be compiled successfully. */
- for (parm = ARG_INFO_PARMS (arg_info), typelt = arg_types, parmno = 1;
+ for (parm = arg_info->parms, typelt = arg_types, parmno = 1;
parm;
parm = TREE_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
{
}
}
-/* Take apart the current scope and return a tree_list node with info
- on a parameter list just parsed. This tree_list node should be
- examined using the ARG_INFO_* macros, defined above:
-
- ARG_INFO_PARMS: a list of parameter decls.
- ARG_INFO_TAGS: a list of structure, union and enum tags defined.
- ARG_INFO_TYPES: a list of argument types to go in the FUNCTION_TYPE.
- ARG_INFO_OTHERS: a list of non-parameter decls (notably enumeration
- constants) defined with the parameters.
+/* Take apart the current scope and return a c_arg_info structure with
+ info on a parameter list just parsed.
- This tree_list node is later fed to 'grokparms' and 'store_parm_decls'.
+ This structure is later fed to 'grokparms' and 'store_parm_decls'.
ELLIPSIS being true means the argument list ended in '...' so don't
append a sentinel (void_list_node) to the end of the type-list. */
-tree
+struct c_arg_info *
get_parm_info (bool ellipsis)
{
struct c_binding *b = current_scope->bindings;
- tree arg_info = make_node (TREE_LIST);
+ struct c_arg_info *arg_info = XOBNEW (&parser_obstack,
+ struct c_arg_info);
tree parms = 0;
tree tags = 0;
tree types = 0;
static bool explained_incomplete_types = false;
bool gave_void_only_once_err = false;
+ arg_info->parms = 0;
+ arg_info->tags = 0;
+ arg_info->types = 0;
+ arg_info->others = 0;
+
/* The bindings in this scope must not get put into a block.
We will take care of deleting the binding nodes. */
current_scope->bindings = 0;
if (ellipsis)
error ("'void' must be the only parameter");
- ARG_INFO_TYPES (arg_info) = void_list_node;
+ arg_info->types = void_list_node;
return arg_info;
}
b = free_binding_and_advance (b);
}
- ARG_INFO_PARMS (arg_info) = parms;
- ARG_INFO_TAGS (arg_info) = tags;
- ARG_INFO_TYPES (arg_info) = types;
- ARG_INFO_OTHERS (arg_info) = others;
+ arg_info->parms = parms;
+ arg_info->tags = tags;
+ arg_info->types = types;
+ arg_info->others = others;
return arg_info;
}
\f
return ref;
}
-/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
+/* Process the specs, declarator and width (NULL if omitted)
of a structure component, returning a FIELD_DECL node.
WIDTH is non-NULL for bit-fields only, and is an INTEGER_CST node.
are ultimately passed to `build_struct' to make the RECORD_TYPE node. */
tree
-grokfield (tree declarator, tree declspecs, tree width)
+grokfield (struct c_declarator *declarator, tree declspecs, tree width)
{
tree value;
- if (declarator == NULL_TREE && width == NULL_TREE)
+ if (declarator->kind == cdk_id && declarator->u.id == NULL_TREE
+ && width == NULL_TREE)
{
/* This is an unnamed decl.
yyparse to report a parse error. */
int
-start_function (tree declspecs, tree declarator, tree attributes)
+start_function (tree declspecs, struct c_declarator *declarator,
+ tree attributes)
{
tree decl1, old_decl;
tree restype, resdecl;
need only record them as in effect and complain if any redundant
old-style parm decls were written. */
static void
-store_parm_decls_newstyle (tree fndecl, tree arg_info)
+store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
{
tree decl;
- tree parms = ARG_INFO_PARMS (arg_info);
- tree tags = ARG_INFO_TAGS (arg_info);
- tree others = ARG_INFO_OTHERS (arg_info);
if (current_scope->bindings)
{
(this happens when a function definition has just an ellipsis in
its parameter list). */
else if (warn_traditional && !in_system_header && !current_function_scope
- && ARG_INFO_TYPES (arg_info) != error_mark_node)
+ && arg_info->types != error_mark_node)
warning ("%Jtraditional C rejects ISO C style function definitions",
fndecl);
/* Now make all the parameter declarations visible in the function body.
We can bypass most of the grunt work of pushdecl. */
- for (decl = parms; decl; decl = TREE_CHAIN (decl))
+ for (decl = arg_info->parms; decl; decl = TREE_CHAIN (decl))
{
DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl))
}
/* Record the parameter list in the function declaration. */
- DECL_ARGUMENTS (fndecl) = parms;
+ DECL_ARGUMENTS (fndecl) = arg_info->parms;
/* Now make all the ancillary declarations visible, likewise. */
- for (decl = others; decl; decl = TREE_CHAIN (decl))
+ for (decl = arg_info->others; decl; decl = TREE_CHAIN (decl))
{
DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl))
}
/* And all the tag declarations. */
- for (decl = tags; decl; decl = TREE_CHAIN (decl))
+ for (decl = arg_info->tags; decl; decl = TREE_CHAIN (decl))
if (TREE_PURPOSE (decl))
bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope,
/*invisible=*/false, /*nested=*/false);
definitions (separate parameter list and declarations). */
static void
-store_parm_decls_oldstyle (tree fndecl, tree arg_info)
+store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
{
struct c_binding *b;
tree parm, decl, last;
- tree parmids = ARG_INFO_PARMS (arg_info);
+ tree parmids = arg_info->parms;
/* We use DECL_WEAK as a flag to show which parameters have been
seen already, since it is not used on PARM_DECL. */
function declaration. */
void
-store_parm_decls_from (tree arg_info)
+store_parm_decls_from (struct c_arg_info *arg_info)
{
current_function_arg_info = arg_info;
store_parm_decls ();
bool proto;
/* The argument information block for FNDECL. */
- tree arg_info = current_function_arg_info;
+ struct c_arg_info *arg_info = current_function_arg_info;
current_function_arg_info = 0;
/* True if this definition is written with a prototype. Note:
list in a function definition as equivalent to (void) -- an
empty argument list specifies the function has no parameters,
but only (void) sets up a prototype for future calls. */
- proto = ARG_INFO_TYPES (arg_info) != 0;
+ proto = arg_info->types != 0;
if (proto)
store_parm_decls_newstyle (fndecl, arg_info);
return t;
}
-/* Return a structure for a parameter with the given SPECS, ATTRS and
- DECLARATOR. */
+/* Return a c_parm structure with the given SPECS, ATTRS and DECLARATOR. */
-tree
-build_c_parm (tree specs, tree attrs, tree declarator)
+struct c_parm *
+build_c_parm (tree specs, tree attrs, struct c_declarator *declarator)
{
- return build_tree_list (build_tree_list (specs, declarator), attrs);
+ struct c_parm *ret = XOBNEW (&parser_obstack, struct c_parm);
+ ret->specs = specs;
+ ret->attrs = attrs;
+ ret->declarator = declarator;
+ return ret;
}
/* Return a declarator with nested attributes. TARGET is the inner
declarator to which these attributes apply. ATTRS are the
attributes. */
-tree
-build_attrs_declarator (tree attrs, tree target)
+struct c_declarator *
+build_attrs_declarator (tree attrs, struct c_declarator *target)
{
- return tree_cons (attrs, target, NULL_TREE);
+ struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+ ret->kind = cdk_attrs;
+ ret->declarator = target;
+ ret->u.attrs = attrs;
+ return ret;
}
/* Return a declarator for a function with arguments specified by ARGS
and return type specified by TARGET. */
-tree
-build_function_declarator (tree args, tree target)
+struct c_declarator *
+build_function_declarator (struct c_arg_info *args,
+ struct c_declarator *target)
{
- return build_nt (CALL_EXPR, target, args, NULL_TREE);
+ struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+ ret->kind = cdk_function;
+ ret->declarator = target;
+ ret->u.arg_info = args;
+ return ret;
+}
+
+/* Return a declarator for the identifier IDENT (which may be
+ NULL_TREE for an abstract declarator). */
+
+struct c_declarator *
+build_id_declarator (tree ident)
+{
+ struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+ ret->kind = cdk_id;
+ ret->declarator = 0;
+ ret->u.id = ident;
+ return ret;
}
/* Return something to represent absolute declarators containing a *.
TARGET is the absolute declarator that the * contains.
TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
to apply to the pointer type, represented as identifiers, possible mixed
- with attributes.
+ with attributes. */
- We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST,
- if attributes are present) and whose type is the modifier list. */
-
-tree
-make_pointer_declarator (tree type_quals_attrs, tree target)
+struct c_declarator *
+make_pointer_declarator (tree type_quals_attrs, struct c_declarator *target)
{
tree quals, attrs;
- tree itarget = target;
+ struct c_declarator *itarget = target;
+ struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
split_specs_attrs (type_quals_attrs, &quals, &attrs);
if (attrs != NULL_TREE)
itarget = build_attrs_declarator (attrs, target);
- return build1 (INDIRECT_REF, quals, itarget);
+ ret->kind = cdk_pointer;
+ ret->declarator = itarget;
+ ret->u.pointer_quals = quals;
+ return ret;
}
/* Synthesize a function which calls all the global ctors or global
%start program
%union {long itype; tree ttype; void *otype; struct c_expr exprtype;
+ struct c_arg_info *arginfotype; struct c_declarator *dtrtype;
+ struct c_type_name *typenametype; struct c_parm *parmtype;
enum tree_code code; location_t location; }
/* All identifiers that are not reserved words
%type <ttype> c99_block_start c99_block_lineno_labeled_stmt
%type <ttype> if_statement_1 if_statement_2
-%type <ttype> declarator
-%type <ttype> notype_declarator after_type_declarator
-%type <ttype> parm_declarator
-%type <ttype> parm_declarator_starttypename parm_declarator_nostarttypename
-%type <ttype> array_declarator
+%type <dtrtype> declarator
+%type <dtrtype> notype_declarator after_type_declarator
+%type <dtrtype> parm_declarator
+%type <dtrtype> parm_declarator_starttypename parm_declarator_nostarttypename
+%type <dtrtype> array_declarator
%type <ttype> structsp_attr structsp_nonattr
%type <ttype> component_decl_list component_decl_list2
%type <ttype> component_notype_declarator
%type <ttype> enumlist enumerator
%type <ttype> struct_head union_head enum_head
-%type <ttype> typename absdcl absdcl1 absdcl1_ea absdcl1_noea
-%type <ttype> direct_absdcl1 absdcl_maybe_attribute
+%type <typenametype> typename
+%type <dtrtype> absdcl absdcl1 absdcl1_ea absdcl1_noea direct_absdcl1
+%type <parmtype> absdcl_maybe_attribute
%type <ttype> condition xexpr for_cond_expr for_incr_expr
-%type <ttype> parms parm firstparm identifiers
+%type <parmtype> parm firstparm
+%type <ttype> identifiers
-%type <ttype> parmlist parmlist_1 parmlist_2
-%type <ttype> parmlist_or_identifiers parmlist_or_identifiers_1
+%type <arginfotype> parms parmlist parmlist_1 parmlist_2
+%type <arginfotype> parmlist_or_identifiers parmlist_or_identifiers_1
%type <ttype> identifiers_or_typenames
%type <itype> setspecs setspecs_fp extension
$$.original_code = ERROR_MARK; }
| '(' typename ')' '{'
{ start_init (NULL_TREE, NULL, 0);
- $2 = groktypename ($2);
- really_start_incremental_init ($2); }
+ $<ttype>$ = groktypename ($2);
+ really_start_incremental_init ($<ttype>$); }
initlist_maybe_comma '}' %prec UNARY
{ struct c_expr init = pop_init_level (0);
tree constructor = init.value;
- tree type = $2;
+ tree type = $<ttype>5;
finish_init ();
maybe_warn_string_init (type, init);
| '*' maybe_type_quals_attrs after_type_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
| TYPENAME
+ { $$ = build_id_declarator ($1); }
@@ifobjc
| OBJECTNAME
+ { $$ = build_id_declarator ($1); }
@@end_ifobjc
;
| parm_declarator_starttypename array_declarator %prec '.'
{ $$ = set_array_declarator_inner ($2, $1, false); }
| TYPENAME
+ { $$ = build_id_declarator ($1); }
@@ifobjc
| OBJECTNAME
+ { $$ = build_id_declarator ($1); }
@@end_ifobjc
;
| notype_declarator array_declarator %prec '.'
{ $$ = set_array_declarator_inner ($2, $1, false); }
| IDENTIFIER
+ { $$ = build_id_declarator ($1); }
;
struct_head:
if (pedantic)
pedwarn ("ISO C doesn't support unnamed structs/unions");
- $$ = grokfield(NULL, current_declspecs, NULL_TREE);
+ $$ = grokfield (build_id_declarator (NULL_TREE),
+ current_declspecs, NULL_TREE);
POP_DECLSPEC_STACK; }
| declspecs_nosc_nots setspecs components_notype
{ $$ = $3;
decl_attributes (&$$,
chainon ($4, all_prefix_attributes), 0); }
| ':' expr_no_commas maybe_attribute
- { $$ = grokfield (NULL_TREE, current_declspecs, $2.value);
+ { $$ = grokfield (build_id_declarator (NULL_TREE),
+ current_declspecs, $2.value);
decl_attributes (&$$,
chainon ($3, all_prefix_attributes), 0); }
;
decl_attributes (&$$,
chainon ($4, all_prefix_attributes), 0); }
| ':' expr_no_commas maybe_attribute
- { $$ = grokfield (NULL_TREE, current_declspecs, $2.value);
+ { $$ = grokfield (build_id_declarator (NULL_TREE),
+ current_declspecs, $2.value);
decl_attributes (&$$,
chainon ($3, all_prefix_attributes), 0); }
;
{ pending_xref_error ();
$<ttype>$ = $1; }
absdcl
- { $$ = build_tree_list ($<ttype>2, $3); }
+ { $$ = XOBNEW (&parser_obstack, struct c_type_name);
+ $$->specs = $<ttype>2;
+ $$->declarator = $3; }
;
absdcl: /* an absolute declarator */
/* empty */
- { $$ = NULL_TREE; }
+ { $$ = build_id_declarator (NULL_TREE); }
| absdcl1
;
absdcl_maybe_attribute: /* absdcl maybe_attribute, but not just attributes */
/* empty */
{ $$ = build_c_parm (current_declspecs, all_prefix_attributes,
- NULL_TREE); }
+ build_id_declarator (NULL_TREE)); }
| absdcl1
{ $$ = build_c_parm (current_declspecs, all_prefix_attributes,
$1); }
absdcl1_ea:
'*' maybe_type_quals_attrs
- { $$ = make_pointer_declarator ($2, NULL_TREE); }
+ { $$ = make_pointer_declarator
+ ($2, build_id_declarator (NULL_TREE)); }
| '*' maybe_type_quals_attrs absdcl1_ea
{ $$ = make_pointer_declarator ($2, $3); }
;
| direct_absdcl1 array_declarator
{ $$ = set_array_declarator_inner ($2, $1, true); }
| '(' parmlist
- { $$ = build_function_declarator ($2, NULL_TREE); }
+ { $$ = build_function_declarator
+ ($2, build_id_declarator (NULL_TREE)); }
| array_declarator
- { $$ = set_array_declarator_inner ($1, NULL_TREE, true); }
+ { $$ = set_array_declarator_inner
+ ($1, build_id_declarator (NULL_TREE), true); }
;
/* The [...] part of a declarator for an array type. */
parmlist_1
{ $$ = $6; }
| error ')'
- { $$ = make_node (TREE_LIST); }
+ { $$ = XOBNEW (&parser_obstack, struct c_arg_info);
+ $$->parms = 0;
+ $$->tags = 0;
+ $$->types = 0;
+ $$->others = 0; }
;
/* This is what appears inside the parens in a function declarator.
- Is value is represented in the format that grokdeclarator expects. */
+ Its value is represented in the format that grokdeclarator expects. */
parmlist_2: /* empty */
- { $$ = make_node (TREE_LIST); }
+ { $$ = XOBNEW (&parser_obstack, struct c_arg_info);
+ $$->parms = 0;
+ $$->tags = 0;
+ $$->types = 0;
+ $$->others = 0; }
| ELLIPSIS
- { $$ = make_node (TREE_LIST);
+ { $$ = XOBNEW (&parser_obstack, struct c_arg_info);
+ $$->parms = 0;
+ $$->tags = 0;
+ $$->others = 0;
/* Suppress -Wold-style-definition for this case. */
- TREE_CHAIN ($$) = error_mark_node;
+ $$->types = error_mark_node;
error ("ISO C requires a named argument before `...'");
}
| parms
parmlist_or_identifiers_1:
parmlist_1
| identifiers ')'
- { $$ = tree_cons (NULL_TREE, NULL_TREE, $1);
+ { $$ = XOBNEW (&parser_obstack, struct c_arg_info);
+ $$->parms = 0;
+ $$->tags = 0;
+ $$->types = $1;
+ $$->others = 0;
/* Make sure we have a parmlist after attributes. */
if ($<ttype>-1 != 0)
enum tree_code original_code;
};
+/* The various kinds of declarators in C. */
+enum c_declarator_kind {
+ /* An identifier. */
+ cdk_id,
+ /* A function. */
+ cdk_function,
+ /* An array. */
+ cdk_array,
+ /* A pointer. */
+ cdk_pointer,
+ /* Parenthesized declarator with nested attributes. */
+ cdk_attrs
+};
+
+/* Information about the parameters in a function declarator. */
+struct c_arg_info {
+ /* A list of parameter decls. */
+ tree parms;
+ /* A list of structure, union and enum tags defined. */
+ tree tags;
+ /* A list of argument types to go in the FUNCTION_TYPE. */
+ tree types;
+ /* A list of non-parameter decls (notably enumeration constants)
+ defined with the parameters. */
+ tree others;
+};
+
+/* A declarator. */
+struct c_declarator {
+ /* The kind of declarator. */
+ enum c_declarator_kind kind;
+ /* Except for cdk_id, the contained declarator. For cdk_id, NULL. */
+ struct c_declarator *declarator;
+ union {
+ /* For identifiers, an IDENTIFIER_NODE or NULL_TREE if an abstract
+ declarator. */
+ tree id;
+ /* For functions. */
+ struct c_arg_info *arg_info;
+ /* For arrays. */
+ struct {
+ /* The array dimension, or NULL for [] and [*]. */
+ tree dimen;
+ /* The qualifiers (and attributes, currently ignored) inside []. */
+ tree quals;
+ /* Whether [static] was used. */
+ BOOL_BITFIELD static_p : 1;
+ /* Whether [*] was used. */
+ BOOL_BITFIELD vla_unspec_p : 1;
+ } array;
+ /* For pointers, the qualifiers on the pointer type. */
+ tree pointer_quals;
+ /* For attributes. */
+ tree attrs;
+ } u;
+};
+
+/* A type name. */
+struct c_type_name {
+ /* The declaration specifiers. */
+ tree specs;
+ /* The declarator. */
+ struct c_declarator *declarator;
+};
+
+/* A parameter. */
+struct c_parm {
+ /* The declaration specifiers, minus any prefix attributes. */
+ tree specs;
+ /* The attributes. */
+ tree attrs;
+ /* The declarator. */
+ struct c_declarator *declarator;
+};
+
/* Save and restore the variables in this file and elsewhere
that keep track of the progress of compilation of the current function.
Used for nested functions. */
tree x_break_label;
tree x_cont_label;
struct c_switch * GTY((skip)) x_switch_stack;
- tree arg_info;
+ struct c_arg_info * GTY((skip)) arg_info;
int returns_value;
int returns_null;
int returns_abnormally;
extern void c_init_decl_processing (void);
extern void c_dup_lang_specific_decl (tree);
extern void c_print_identifier (FILE *, tree, int);
-extern tree build_array_declarator (tree, tree, bool, bool);
+extern struct c_declarator *build_array_declarator (tree, tree, bool, bool);
extern tree build_enumerator (tree, tree);
extern void check_for_loop_decls (void);
extern void mark_forward_parm_decls (void);
extern tree finish_enum (tree, tree, tree);
extern void finish_function (void);
extern tree finish_struct (tree, tree, tree);
-extern tree get_parm_info (bool);
-extern tree grokfield (tree, tree, tree);
+extern struct c_arg_info *get_parm_info (bool);
+extern tree grokfield (struct c_declarator *, tree, tree);
extern void split_specs_attrs (tree, tree *, tree *);
-extern tree groktypename (tree);
-extern tree grokparm (tree);
+extern tree groktypename (struct c_type_name *);
+extern tree grokparm (const struct c_parm *);
extern tree implicitly_declare (tree);
extern void keep_next_level (void);
extern tree lookup_name (tree);
extern void pending_xref_error (void);
extern void c_push_function_context (struct function *);
extern void c_pop_function_context (struct function *);
-extern void push_parm_decl (tree);
+extern void push_parm_decl (const struct c_parm *);
extern tree pushdecl_top_level (tree);
-extern tree set_array_declarator_inner (tree, tree, bool);
+extern struct c_declarator *set_array_declarator_inner (struct c_declarator *,
+ struct c_declarator *,
+ bool);
extern tree builtin_function (const char *, tree, int, enum built_in_class,
const char *, tree);
extern void shadow_tag (tree);
extern void shadow_tag_warned (tree, int);
extern tree start_enum (tree);
-extern int start_function (tree, tree, tree);
-extern tree start_decl (tree, tree, bool, tree);
+extern int start_function (tree, struct c_declarator *, tree);
+extern tree start_decl (struct c_declarator *, tree, bool, tree);
extern tree start_struct (enum tree_code, tree);
extern void store_parm_decls (void);
-extern void store_parm_decls_from (tree);
+extern void store_parm_decls_from (struct c_arg_info *);
extern tree xref_tag (enum tree_code, tree);
extern int c_expand_decl (tree);
-extern tree build_c_parm (tree, tree, tree);
-extern tree build_attrs_declarator (tree, tree);
-extern tree build_function_declarator (tree, tree);
-extern tree make_pointer_declarator (tree, tree);
+extern struct c_parm *build_c_parm (tree, tree, struct c_declarator *);
+extern struct c_declarator *build_attrs_declarator (tree,
+ struct c_declarator *);
+extern struct c_declarator *build_function_declarator (struct c_arg_info *,
+ struct c_declarator *);
+extern struct c_declarator *build_id_declarator (tree);
+extern struct c_declarator *make_pointer_declarator (tree,
+ struct c_declarator *);
/* in c-objc-common.c */
extern int c_disregard_inline_limits (tree);
extern void record_maybe_used_decl (tree);
extern void pop_maybe_used (bool);
extern struct c_expr c_expr_sizeof_expr (struct c_expr);
-extern struct c_expr c_expr_sizeof_type (tree);
+extern struct c_expr c_expr_sizeof_type (struct c_type_name *);
extern struct c_expr parser_build_binary_op (enum tree_code, struct c_expr,
struct c_expr);
extern void readonly_error (tree, const char *);
extern tree build_conditional_expr (tree, tree, tree);
extern tree build_compound_expr (tree, tree);
-extern tree c_cast_expr (tree, tree);
+extern tree c_cast_expr (struct c_type_name *, tree);
extern tree build_c_cast (tree, tree);
extern tree build_modify_expr (tree, enum tree_code, tree);
extern void store_init_value (tree, tree);