Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
/* Process declarations and symbol lookup for C front end.
Also constructs types; the standard scalar types at initialization,
#include "ggc.h"
#include "tm_p.h"
#include "cpplib.h"
+#include "target.h"
+#include "debug.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
char **argv;
{
int strings_processed;
- const char *option_value = NULL;
char *p = argv[0];
strings_processed = cpp_handle_option (parse_in, argc, argv);
-std=gnu89 default, iso9899:1990 + gnu extensions
-std=gnu99 iso9899:1999 + gnu extensions
*/
- const char *argstart = &p[5];
+ const char *const argstart = &p[5];
if (!strcmp (argstart, "iso9899:1990")
|| !strcmp (argstart, "c89"))
flag_no_builtin = 0;
else if (!strcmp (p, "-fno-builtin"))
flag_no_builtin = 1;
- else if ((option_value
- = skip_leading_substring (p, "-fdump-translation-unit-")))
- {
- if (p[22] == '\0')
- error ("no file specified with -fdump-translation-unit");
- else
- flag_dump_translation_unit = option_value;
- }
+ else if (p[0] == '-' && p[1] == 'f' && dump_switch_p (p + 2))
+ ;
else if (!strcmp (p, "-ansi"))
goto iso_1990;
else if (!strcmp (p, "-Werror-implicit-function-declaration"))
int errmsg = 0;
if (DECL_P (olddecl))
- DECL_MACHINE_ATTRIBUTES (newdecl)
- = merge_machine_decl_attributes (olddecl, newdecl);
+ DECL_ATTRIBUTES (newdecl)
+ = (*targetm.merge_decl_attributes) (olddecl, newdecl);
if (TREE_CODE (newtype) == ERROR_MARK
|| TREE_CODE (oldtype) == ERROR_MARK)
been written out yet. */
if (new_is_definition && DECL_INITIAL (olddecl) && TREE_USED (olddecl))
{
- note_outlining_of_inline_function (olddecl);
+ (*debug_hooks->outlining_inline_function) (olddecl);
/* The new defn must not be inline. */
DECL_INLINE (newdecl) = 0;
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
- DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
+ DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
return 1;
}
implicitly_declare (functionid)
tree functionid;
{
- register tree decl;
+ tree decl;
int traditional_warning = 0;
/* Only one "implicit declaration" warning per identifier. */
int implicit_warning;
gen_aux_info_record (decl, 0, 1, 0);
+ /* Possibly apply some default attributes to this implicit declaration. */
+ decl_attributes (&decl, NULL_TREE, 0);
+
return decl;
}
g77_ulongint_type_node));
}
- builtin_function ("__builtin_aggregate_incoming_address",
- build_function_type (ptr_type_node, NULL_TREE),
- BUILT_IN_AGGREGATE_INCOMING_ADDRESS,
- BUILT_IN_NORMAL, NULL);
-
- /* Hooks for the DWARF 2 __throw routine. */
- builtin_function ("__builtin_unwind_init",
- build_function_type (void_type_node, endlink),
- BUILT_IN_UNWIND_INIT, BUILT_IN_NORMAL, NULL);
- builtin_function ("__builtin_dwarf_cfa", ptr_ftype_void,
- BUILT_IN_DWARF_CFA, BUILT_IN_NORMAL, NULL);
- builtin_function ("__builtin_dwarf_fp_regnum",
- build_function_type (unsigned_type_node, endlink),
- BUILT_IN_DWARF_FP_REGNUM, BUILT_IN_NORMAL, NULL);
- builtin_function ("__builtin_init_dwarf_reg_size_table", void_ftype_ptr,
- BUILT_IN_INIT_DWARF_REG_SIZES, BUILT_IN_NORMAL, NULL);
- builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
- BUILT_IN_FROB_RETURN_ADDR, BUILT_IN_NORMAL, NULL);
- builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
- BUILT_IN_EXTRACT_RETURN_ADDR, BUILT_IN_NORMAL, NULL);
- builtin_function
- ("__builtin_eh_return",
- build_function_type (void_type_node,
- tree_cons (NULL_TREE,
- type_for_mode (ptr_mode, 0),
- tree_cons (NULL_TREE,
- ptr_type_node,
- endlink))),
- BUILT_IN_EH_RETURN, BUILT_IN_NORMAL, NULL);
-
pedantic_lvalues = pedantic;
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
- start_identifier_warnings ();
-
- /* Prepare to check format strings against argument lists. */
- init_function_format_info ();
-
incomplete_decl_finalize_hook = finish_incomplete_decl;
/* Record our roots. */
build_index_type (size_int (length)));
decl = build_decl (VAR_DECL, id, type);
- /* We don't push the decl, so have to set its context here. */
+ /* We don't push the decl, so have to set its context here. */
DECL_CONTEXT (decl) = current_function_decl;
TREE_STATIC (decl) = 1;
if (name[0] != '_' || name[1] != '_')
C_DECL_ANTICIPATED (decl) = 1;
+ /* Possibly apply some default attributes to this built-in function. */
+ decl_attributes (&decl, NULL_TREE, 0);
+
return decl;
}
+
+/* Apply default attributes to a function, if a system function with default
+ attributes. */
+
+void
+insert_default_attributes (decl)
+ tree decl;
+{
+ if (!TREE_PUBLIC (decl))
+ return;
+ c_common_insert_default_attributes (decl);
+}
\f
/* Called when a declaration is seen that contains no names to declare.
If its type is a reference to a structure, union or enum inherited
}
}
\f
+/* Construct an array declarator. EXPR is the expression inside [], or
+ NULL_TREE. QUALS are the type qualifiers inside the [] (to be applied
+ to the pointer to which a parameter array is converted). STATIC_P is
+ non-zero if "static" is inside the [], zero otherwise. VLA_UNSPEC_P
+ is non-zero is the array is [*], a VLA of unspecified length which is
+ nevertheless a complete type (not currently implemented by GCC),
+ zero 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_type) and operand 1
+ is the expression inside; whose TREE_TYPE is the type qualifiers and
+ which has TREE_STATIC set if "static" is used. */
+
+tree
+build_array_declarator (expr, quals, static_p, vla_unspec_p)
+ tree expr;
+ tree quals;
+ int static_p;
+ int vla_unspec_p;
+{
+ tree decl;
+ decl = build_nt (ARRAY_REF, NULL_TREE, expr);
+ TREE_TYPE (decl) = quals;
+ TREE_STATIC (decl) = (static_p ? 1 : 0);
+ if (pedantic && !flag_isoc99)
+ {
+ if (static_p || quals != NULL_TREE)
+ pedwarn ("ISO C89 does not support `static' or type qualifiers in parameter array declarators");
+ if (vla_unspec_p)
+ pedwarn ("ISO C89 does not support `[*]' array declarators");
+ }
+ if (vla_unspec_p)
+ warning ("GCC does not yet properly implement `[*]' array declarators");
+ return decl;
+}
+
+/* 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 non-zero if it is an
+ abstract declarator, zero otherwise; this is used to reject static and
+ type qualifiers in abstract declarators, where they are not in the
+ C99 grammar. */
+
+tree
+set_array_declarator_type (decl, type, abstract_p)
+ tree decl;
+ tree type;
+ int abstract_p;
+{
+ TREE_OPERAND (decl, 0) = type;
+ if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
+ error ("static or type qualifiers in abstract declarator");
+ return decl;
+}
+\f
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
tree
grokfield and not through here. */
tree
-start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
+start_decl (declarator, declspecs, initialized, attributes)
tree declarator, declspecs;
int initialized;
- tree attributes, prefix_attributes;
+ tree attributes;
{
- register tree decl = grokdeclarator (declarator, declspecs,
- NORMAL, initialized);
+ tree decl = grokdeclarator (declarator, declspecs,
+ NORMAL, initialized);
register tree tem;
if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
if (! flag_no_common || ! TREE_PUBLIC (decl))
DECL_COMMON (decl) = 1;
-#ifdef SET_DEFAULT_DECL_ATTRIBUTES
- SET_DEFAULT_DECL_ATTRIBUTES (decl, attributes);
-#endif
-
/* Set attributes here so if duplicate decl, will have proper attributes. */
- decl_attributes (decl, attributes, prefix_attributes);
+ decl_attributes (&decl, attributes, 0);
/* Add this decl to the current binding level.
TEM may equal DECL or it may be a previous decl of the same name. */
}
else
{
+ /* This is a local variable. If there is an ASMSPEC, the
+ user has requested that we handle it specially. */
if (asmspec)
{
- SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
- DECL_C_HARD_REGISTER (decl) = 1;
+ /* In conjunction with an ASMSPEC, the `register'
+ keyword indicates that we should place the variable
+ in a particular register. */
+ if (DECL_REGISTER (decl))
+ DECL_C_HARD_REGISTER (decl) = 1;
+
+ /* If this is not a static variable, issue a warning.
+ It doesn't make any sense to give an ASMSPEC for an
+ ordinary, non-register local variable. Historically,
+ GCC has accepted -- but ignored -- the ASMSPEC in
+ this case. */
+ if (TREE_CODE (decl) == VAR_DECL
+ && !DECL_REGISTER (decl)
+ && !TREE_STATIC (decl))
+ warning_with_decl (decl,
+ "ignoring asm-specifier for non-static local variable `%s'");
+ else
+ SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
}
+
add_decl_stmt (decl);
}
decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
TREE_PURPOSE (TREE_PURPOSE (parm)), PARM, 0);
- decl_attributes (decl, TREE_VALUE (TREE_VALUE (parm)),
- TREE_PURPOSE (TREE_VALUE (parm)));
+ decl_attributes (&decl, TREE_VALUE (parm), 0);
#if 0
if (DECL_NAME (decl))
enum tree_code innermost_code = ERROR_MARK;
int bitfield = 0;
int size_varies = 0;
- tree decl_machine_attr = NULL_TREE;
+ tree decl_attr = NULL_TREE;
+ tree array_ptr_quals = NULL_TREE;
+ int array_parm_static = 0;
+ tree returned_attrs = NULL_TREE;
if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
decl = TREE_OPERAND (decl, 0);
break;
+ case TREE_LIST:
+ decl = TREE_VALUE (decl);
+ break;
+
case IDENTIFIER_NODE:
name = IDENTIFIER_POINTER (decl);
decl = 0;
else if (TREE_CODE (id) == TYPE_DECL)
{
type = TREE_TYPE (id);
- decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
+ decl_attr = DECL_ATTRIBUTES (id);
typedef_decl = id;
}
/* Built-in types come as identifiers. */
/* 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
where the name was omitted).
array or function or pointer, and DECLARATOR has had its
outermost layer removed. */
- if (TREE_CODE (declarator) == ARRAY_REF)
+ if (array_ptr_quals != NULL_TREE || array_parm_static)
+ {
+ /* Only the innermost declarator (making a parameter be of
+ array type which is converted to pointer type)
+ may have static or type qualifiers. */
+ error ("static or type qualifiers in non-parameter array declarator");
+ array_ptr_quals = NULL_TREE;
+ array_parm_static = 0;
+ }
+
+ if (TREE_CODE (declarator) == TREE_LIST)
+ {
+ /* We encode a declarator with embedded attributes using
+ a TREE_LIST. */
+ tree attrs = TREE_PURPOSE (declarator);
+ tree inner_decl;
+ int attr_flags = 0;
+ declarator = TREE_VALUE (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)
+ 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);
+ }
+ else if (TREE_CODE (declarator) == ARRAY_REF)
{
register tree itype = NULL_TREE;
register tree size = TREE_OPERAND (declarator, 1);
/* The index is a signed object `sizetype' bits wide. */
tree index_type = signed_type (sizetype);
+ array_ptr_quals = TREE_TYPE (declarator);
+ array_parm_static = TREE_STATIC (declarator);
+
declarator = TREE_OPERAND (declarator, 0);
/* Check for some types that there cannot be arrays of. */
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
STRIP_TYPE_NOPS (size);
- if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE)
+ if (! INTEGRAL_TYPE_P (TREE_TYPE (size)))
{
error ("size of array `%s' has non-integer type", name);
size = integer_one_node;
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
}
+ if (decl_context != PARM
+ && (array_ptr_quals != NULL_TREE || array_parm_static))
+ {
+ error ("static or type qualifiers in non-parameter array declarator");
+ array_ptr_quals = NULL_TREE;
+ array_parm_static = 0;
+ }
}
else if (TREE_CODE (declarator) == CALL_EXPR)
{
if ((specbits & (1 << (int) RID_SIGNED))
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
+ decl_attributes (&decl, returned_attrs, 0);
return decl;
}
pedwarn ("ISO C forbids const or volatile function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
+ decl_attributes (&type, returned_attrs, 0);
return type;
}
or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */
{
- register tree decl;
+ tree decl;
if (decl_context == PARM)
{
- tree type_as_written = type;
+ tree type_as_written;
tree promoted_type;
/* A parameter declared as an array of T is really a pointer to T.
type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
type_quals = TYPE_UNQUALIFIED;
+ if (array_ptr_quals)
+ {
+ tree new_ptr_quals, new_ptr_attrs;
+ int erred = 0;
+ split_specs_attrs (array_ptr_quals, &new_ptr_quals, &new_ptr_attrs);
+ /* We don't yet implement attributes in this context. */
+ if (new_ptr_attrs != NULL_TREE)
+ warning ("attributes in parameter array declarator ignored");
+
+ constp = 0;
+ volatilep = 0;
+ restrictp = 0;
+ for (; new_ptr_quals; new_ptr_quals = TREE_CHAIN (new_ptr_quals))
+ {
+ tree qualifier = TREE_VALUE (new_ptr_quals);
+
+ if (C_IS_RESERVED_WORD (qualifier))
+ {
+ if (C_RID_CODE (qualifier) == RID_CONST)
+ constp++;
+ else if (C_RID_CODE (qualifier) == RID_VOLATILE)
+ volatilep++;
+ else if (C_RID_CODE (qualifier) == RID_RESTRICT)
+ restrictp++;
+ else
+ erred++;
+ }
+ else
+ erred++;
+ }
+
+ if (erred)
+ error ("invalid type modifier within array declarator");
+
+ type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+ | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+ | (volatilep ? TYPE_QUAL_VOLATILE : 0));
+ }
size_varies = 0;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
type = build_pointer_type (type);
type_quals = TYPE_UNQUALIFIED;
}
+ else if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
+
+ type_as_written = type;
decl = build_decl (PARM_DECL, declarator, type);
if (size_varies)
pedwarn ("invalid storage class for function `%s'", name);
decl = build_decl (FUNCTION_DECL, declarator, type);
- decl = build_decl_attribute_variant (decl, decl_machine_attr);
+ decl = build_decl_attribute_variant (decl, decl_attr);
if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ISO C forbids qualified function types");
type_quals = TYPE_UNQUALIFIED;
#endif
}
-
+ else if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
+
decl = build_decl (VAR_DECL, declarator, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
mark_addressable (decl);
+ decl_attributes (&decl, returned_attrs, 0);
+
return decl;
}
}
tree type = TREE_TYPE (decl);
DECL_ARG_TYPE (decl) = type;
if (PROMOTE_PROTOTYPES
- && (TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
+ && INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (decl) = integer_type_node;
already defined for this tag and return it. */
register tree ref = lookup_tag (code, name, current_binding_level, 0);
- /* Even if this is the wrong type of tag, return what we found.
- There will be an error message anyway, from pending_xref_error.
- If we create an empty xref just for an invalid use of the type,
- the main result is to create lots of superfluous error messages. */
- if (ref)
+ /* If this is the right type of tag, return what we found.
+ (This reference will be shadowed by shadow_tag later if appropriate.)
+ If this is the wrong type of tag, do not return it. If it was the
+ wrong type in the same binding level, we will have had an error
+ message already; if in a different binding level and declaring
+ a name, pending_xref_error will give an error message; but if in a
+ different binding level and not declaring a name, this tag should
+ shadow the previous declaration of a different type of tag, and
+ this would not work properly if we return the reference found.
+ (For example, with "struct foo" in an outer scope, "union foo;"
+ must shadow that tag with a new one of union type.) */
+ if (ref && TREE_CODE (ref) == code)
return ref;
/* If no such tag is yet defined, create a forward-reference node
TYPE_SIZE (t) = 0;
- decl_attributes (t, attributes, NULL_TREE);
+ decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
/* Nameless union parm types are useful as GCC extension. */
if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic)
if (in_parm_level_p ())
warning ("enum defined inside parms");
- decl_attributes (enumtype, attributes, NULL_TREE);
+ decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
/* Calculate the maximum value of any enumerator in this type. */
\f
/* Create the FUNCTION_DECL for a function definition.
- DECLSPECS, DECLARATOR, PREFIX_ATTRIBUTES and ATTRIBUTES are the parts of
+ DECLSPECS, DECLARATOR and ATTRIBUTES are the parts of
the declaration; they describe the function's name and the type it returns,
but twisted together in a fashion that parallels the syntax of C.
yyparse to report a parse error. */
int
-start_function (declspecs, declarator, prefix_attributes, attributes)
- tree declarator, declspecs, prefix_attributes, attributes;
+start_function (declspecs, declarator, attributes)
+ tree declarator, declspecs, attributes;
{
tree decl1, old_decl;
tree restype;
return 0;
}
- decl_attributes (decl1, prefix_attributes, attributes);
+ decl_attributes (&decl1, attributes, 0);
announce_function (decl1);
except for defining how to inline. So set DECL_EXTERNAL in that case. */
DECL_EXTERNAL (decl1) = current_extern_inline;
-#ifdef SET_DEFAULT_DECL_ATTRIBUTES
- SET_DEFAULT_DECL_ATTRIBUTES (decl1, attributes);
-#endif
-
/* This function exists in static storage.
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
/* Nonzero if this definition is written with a prototype. */
int prototype = 0;
+ /* The function containing FNDECL, if any. */
+ tree context = decl_function_context (fndecl);
+
if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST)
{
/* This case is when the function was defined with an ANSI prototype.
"prototype declaration");
break;
}
- /* Type for passing arg must be consistent
- with that declared for the arg. */
- if (! comptypes (DECL_ARG_TYPE (parm), TREE_VALUE (type)))
+ /* Type for passing arg must be consistent with that
+ declared for the arg. ISO C says we take the unqualified
+ type for parameters declared with qualified type. */
+ if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
+ TYPE_MAIN_VARIANT (TREE_VALUE (type))))
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
== TYPE_MAIN_VARIANT (TREE_VALUE (type)))
DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
if (PROMOTE_PROTOTYPES
- && (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
- || TREE_CODE (TREE_TYPE (parm)) == ENUMERAL_TYPE)
+ && INTEGRAL_TYPE_P (TREE_TYPE (parm))
&& TYPE_PRECISION (TREE_TYPE (parm))
< TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (parm) = integer_type_node;
gen_aux_info_record (fndecl, 1, 0, prototype);
/* Initialize the RTL code for the function. */
-
init_function_start (fndecl, input_filename, lineno);
/* Begin the statement tree for this function. */
DECL_LANG_SPECIFIC (current_function_decl)
- =((struct lang_decl *) ggc_alloc (sizeof (struct lang_decl)));
+ =((struct lang_decl *) ggc_alloc_cleared (sizeof (struct lang_decl)));
begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
+ /* If this is a nested function, save away the sizes of any
+ variable-size types so that we can expand them when generating
+ RTL. */
+ if (context)
+ {
+ tree t;
+
+ DECL_LANG_SPECIFIC (fndecl)->pending_sizes
+ = nreverse (get_pending_sizes ());
+ for (t = DECL_LANG_SPECIFIC (fndecl)->pending_sizes;
+ t;
+ t = TREE_CHAIN (t))
+ SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = context;
+ }
+
/* This function is being processed in whole-function mode. */
cfun->x_whole_function_mode_p = 1;
cfun->x_dont_save_pending_sizes_p = 1;
}
\f
-/* SPECPARMS is an identifier list--a chain of TREE_LIST nodes
- each with a parm name as the TREE_VALUE. A null pointer as TREE_VALUE
- stands for an ellipsis in the identifier list.
-
- PARMLIST is the data returned by get_parm_info for the
- parmlist that follows the semicolon.
-
- We return a value of the same sort that get_parm_info returns,
- except that it describes the combination of identifiers and parmlist. */
-
-tree
-combine_parm_decls (specparms, parmlist, void_at_end)
- tree specparms, parmlist;
- int void_at_end;
-{
- register tree fndecl = current_function_decl;
- register tree parm;
-
- tree parmdecls = TREE_PURPOSE (parmlist);
-
- /* This is a chain of any other decls that came in among the parm
- declarations. They were separated already by get_parm_info,
- so we just need to keep them separate. */
- tree nonparms = TREE_VALUE (parmlist);
-
- tree types = 0;
-
- for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
- DECL_WEAK (parm) = 0;
-
- for (parm = specparms; parm; parm = TREE_CHAIN (parm))
- {
- register tree tail, found = NULL;
-
- /* See if any of the parmdecls specifies this parm by name. */
- for (tail = parmdecls; tail; tail = TREE_CHAIN (tail))
- if (DECL_NAME (tail) == TREE_VALUE (parm))
- {
- found = tail;
- break;
- }
-
- /* If declaration already marked, we have a duplicate name.
- Complain, and don't use this decl twice. */
- if (found && DECL_WEAK (found))
- {
- error_with_decl (found, "multiple parameters named `%s'");
- found = 0;
- }
-
- /* If the declaration says "void", complain and ignore it. */
- if (found && VOID_TYPE_P (TREE_TYPE (found)))
- {
- error_with_decl (found, "parameter `%s' declared void");
- TREE_TYPE (found) = integer_type_node;
- DECL_ARG_TYPE (found) = integer_type_node;
- layout_decl (found, 0);
- }
-
- /* Traditionally, a parm declared float is actually a double. */
- if (found && flag_traditional
- && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == float_type_node)
- {
- TREE_TYPE (found) = double_type_node;
- DECL_ARG_TYPE (found) = double_type_node;
- layout_decl (found, 0);
- }
-
- /* If no declaration found, default to int. */
- if (!found)
- {
- found = build_decl (PARM_DECL, TREE_VALUE (parm),
- integer_type_node);
- DECL_ARG_TYPE (found) = TREE_TYPE (found);
- DECL_SOURCE_LINE (found) = DECL_SOURCE_LINE (fndecl);
- DECL_SOURCE_FILE (found) = DECL_SOURCE_FILE (fndecl);
- error_with_decl (found, "type of parameter `%s' is not declared");
- pushdecl (found);
- }
-
- TREE_PURPOSE (parm) = found;
-
- /* Mark this decl as "already found". */
- DECL_WEAK (found) = 1;
- }
-
- /* Complain about any actual PARM_DECLs not matched with any names. */
-
- for (parm = parmdecls; parm;)
- {
- tree next = TREE_CHAIN (parm);
- TREE_CHAIN (parm) = 0;
-
- /* Complain about args with incomplete types. */
- if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
- {
- error_with_decl (parm, "parameter `%s' has incomplete type");
- TREE_TYPE (parm) = error_mark_node;
- }
-
- if (! DECL_WEAK (parm))
- {
- error_with_decl (parm,
- "declaration for parameter `%s' but no such parameter");
- /* Pretend the parameter was not missing.
- This gets us to a standard state and minimizes
- further error messages. */
- specparms
- = chainon (specparms,
- tree_cons (parm, NULL_TREE, NULL_TREE));
- }
-
- parm = next;
- }
-
- /* Chain the declarations together in the order of the list of names.
- At the same time, build up a list of their types, in reverse order. */
-
- parm = specparms;
- parmdecls = 0;
- {
- register tree last;
- for (last = 0; parm; parm = TREE_CHAIN (parm))
- if (TREE_PURPOSE (parm))
- {
- if (last == 0)
- parmdecls = TREE_PURPOSE (parm);
- else
- TREE_CHAIN (last) = TREE_PURPOSE (parm);
- last = TREE_PURPOSE (parm);
- TREE_CHAIN (last) = 0;
-
- types = tree_cons (NULL_TREE, TREE_TYPE (parm), types);
- }
- }
-
- if (void_at_end)
- return tree_cons (parmdecls, nonparms,
- nreverse (tree_cons (NULL_TREE, void_type_node, types)));
-
- return tree_cons (parmdecls, nonparms, nreverse (types));
-}
-\f
/* Finish up a function declaration and compile that function
all the way to assembler language output. The free the storage
for the function definition.
if (flag_syntax_only)
return;
- /* Squirrel away our current state. */
if (nested_p)
- push_function_context ();
+ {
+ /* Make sure that we will evaluate variable-sized types involved
+ in our function's type. */
+ expand_pending_sizes (DECL_LANG_SPECIFIC (fndecl)->pending_sizes);
+ /* Squirrel away our current state. */
+ push_function_context ();
+ }
/* Initialize the RTL code for the function. */
current_function_decl = fndecl;
/* Allow the body of the function to be garbage collected. */
DECL_SAVED_TREE (fndecl) = NULL_TREE;
- /* We hard-wired immediate_size_expand to zero in start_function.
+ /* We hard-wired immediate_size_expand to zero above.
expand_function_end will decrement this variable. So, we set the
variable to one here, so that after the decrement it will remain
zero. */
if (DECL_STATIC_CONSTRUCTOR (fndecl))
{
-#ifndef ASM_OUTPUT_CONSTRUCTOR
- if (! flag_gnu_linker)
- static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
+ if (targetm.have_ctors_dtors)
+ (* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
+ DEFAULT_INIT_PRIORITY);
else
-#endif
- assemble_constructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
-
+ static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
}
+
if (DECL_STATIC_DESTRUCTOR (fndecl))
{
-#ifndef ASM_OUTPUT_DESTRUCTOR
- if (! flag_gnu_linker)
- static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
+ if (targetm.have_ctors_dtors)
+ (* targetm.asm_out.destructor) (XEXP (DECL_RTL (fndecl), 0),
+ DEFAULT_INIT_PRIORITY);
else
-#endif
- assemble_destructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
+ static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
}
if (nested_p)
- {
- /* Return to the enclosing function. */
- pop_function_context ();
- /* If the nested function was inline, write it out if that is
- necessary. */
- if (!TREE_ASM_WRITTEN (fndecl) && TREE_ADDRESSABLE (fndecl))
- {
- push_function_context ();
- output_inline_function (fndecl);
- pop_function_context ();
- }
- }
-
+ /* Return to the enclosing function. */
+ pop_function_context ();
}
\f
/* Check the declarations given in a for-loop for satisfying the C99
{
ggc_mark (DECL_LANG_SPECIFIC (t));
c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base);
+ ggc_mark_tree (DECL_LANG_SPECIFIC (t)->pending_sizes);
}
}