diff options
author | cvs2svn <cvs2svn@FreeBSD.org> | 2001-12-18 04:13:59 +0000 |
---|---|---|
committer | cvs2svn <cvs2svn@FreeBSD.org> | 2001-12-18 04:13:59 +0000 |
commit | 8baceaba7914799fb78a4a8a177423bab95a6fae (patch) | |
tree | cd1904fa8adf734febb3ac5d4d64250908ee2713 /contrib/gcc/c-decl.c | |
parent | 8489cc4415b1edcaf1bfe1bc43893024b91b599d (diff) |
This commit was manufactured by cvs2svn to create tagvendor/gcc/3.0.2
'gcc-vendor-gcc_3_0_2'.
Notes
Notes:
svn path=/vendor/gcc/dist/; revision=88109
svn path=/vendor/gcc/3.0.2/; revision=88111; tag=vendor/gcc/3.0.2
Diffstat (limited to 'contrib/gcc/c-decl.c')
-rw-r--r-- | contrib/gcc/c-decl.c | 7453 |
1 files changed, 0 insertions, 7453 deletions
diff --git a/contrib/gcc/c-decl.c b/contrib/gcc/c-decl.c deleted file mode 100644 index 6f8a90068112..000000000000 --- a/contrib/gcc/c-decl.c +++ /dev/null @@ -1,7453 +0,0 @@ -/* Process declarations and variables for C compiler. - Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 - Free Software Foundation, Inc. - -This file is part of GNU CC. - -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. - -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. - -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. */ - - -/* Process declarations and symbol lookup for C front end. - Also constructs types; the standard scalar types at initialization, - and structure, union, array and enum types when they are declared. */ - -/* ??? not all decl nodes are given the most useful possible - line numbers. For example, the CONST_DECLs for enum values. */ - -#include "config.h" -#include "system.h" -#include "tree.h" -#include "flags.h" -#include "output.h" -#include "c-tree.h" -#include "c-lex.h" -#include "toplev.h" - -#if USE_CPPLIB -#include "cpplib.h" -extern cpp_reader parse_in; -#endif - -/* In grokdeclarator, distinguish syntactic contexts of declarators. */ -enum decl_context -{ NORMAL, /* Ordinary declaration */ - FUNCDEF, /* Function definition */ - PARM, /* Declaration of parm before function body */ - FIELD, /* Declaration inside struct or union */ - BITFIELD, /* Likewise but with specified width */ - TYPENAME}; /* Typename (inside cast or sizeof) */ - -#ifndef CHAR_TYPE_SIZE -#define CHAR_TYPE_SIZE BITS_PER_UNIT -#endif - -#ifndef SHORT_TYPE_SIZE -#define SHORT_TYPE_SIZE (BITS_PER_UNIT * MIN ((UNITS_PER_WORD + 1) / 2, 2)) -#endif - -#ifndef INT_TYPE_SIZE -#define INT_TYPE_SIZE BITS_PER_WORD -#endif - -#ifndef LONG_TYPE_SIZE -#define LONG_TYPE_SIZE BITS_PER_WORD -#endif - -#ifndef LONG_LONG_TYPE_SIZE -#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2) -#endif - -#ifndef WCHAR_UNSIGNED -#define WCHAR_UNSIGNED 0 -#endif - -#ifndef FLOAT_TYPE_SIZE -#define FLOAT_TYPE_SIZE BITS_PER_WORD -#endif - -#ifndef DOUBLE_TYPE_SIZE -#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2) -#endif - -#ifndef LONG_DOUBLE_TYPE_SIZE -#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2) -#endif - -/* We let tm.h override the types used here, to handle trivial differences - such as the choice of unsigned int or long unsigned int for size_t. - When machines start needing nontrivial differences in the size type, - it would be best to do something here to figure out automatically - from other information what type to use. */ - -#ifndef SIZE_TYPE -#define SIZE_TYPE "long unsigned int" -#endif - -#ifndef PTRDIFF_TYPE -#define PTRDIFF_TYPE "long int" -#endif - -#ifndef WCHAR_TYPE -#define WCHAR_TYPE "int" -#endif - -/* a node which has tree code ERROR_MARK, and whose type is itself. - All erroneous expressions are replaced with this node. All functions - that accept nodes as arguments should avoid generating error messages - if this node is one of the arguments, since it is undesirable to get - multiple error messages from one error in the input. */ - -tree error_mark_node; - -/* INTEGER_TYPE and REAL_TYPE nodes for the standard data types */ - -tree short_integer_type_node; -tree integer_type_node; -tree long_integer_type_node; -tree long_long_integer_type_node; - -tree short_unsigned_type_node; -tree unsigned_type_node; -tree long_unsigned_type_node; -tree long_long_unsigned_type_node; - -tree boolean_type_node; -tree boolean_false_node; -tree boolean_true_node; - -tree ptrdiff_type_node; - -tree unsigned_char_type_node; -tree signed_char_type_node; -tree char_type_node; -tree wchar_type_node; -tree signed_wchar_type_node; -tree unsigned_wchar_type_node; - -tree float_type_node; -tree double_type_node; -tree long_double_type_node; - -tree complex_integer_type_node; -tree complex_float_type_node; -tree complex_double_type_node; -tree complex_long_double_type_node; - -tree intQI_type_node; -tree intHI_type_node; -tree intSI_type_node; -tree intDI_type_node; -#if HOST_BITS_PER_WIDE_INT >= 64 -tree intTI_type_node; -#endif - -tree unsigned_intQI_type_node; -tree unsigned_intHI_type_node; -tree unsigned_intSI_type_node; -tree unsigned_intDI_type_node; -#if HOST_BITS_PER_WIDE_INT >= 64 -tree unsigned_intTI_type_node; -#endif - -/* a VOID_TYPE node. */ - -tree void_type_node; - -/* Nodes for types `void *' and `const void *'. */ - -tree ptr_type_node, const_ptr_type_node; - -/* Nodes for types `char *' and `const char *'. */ - -tree string_type_node, const_string_type_node; - -/* Type `char[SOMENUMBER]'. - Used when an array of char is needed and the size is irrelevant. */ - -tree char_array_type_node; - -/* Type `int[SOMENUMBER]' or something like it. - Used when an array of int needed and the size is irrelevant. */ - -tree int_array_type_node; - -/* Type `wchar_t[SOMENUMBER]' or something like it. - Used when a wide string literal is created. */ - -tree wchar_array_type_node; - -/* type `int ()' -- used for implicit declaration of functions. */ - -tree default_function_type; - -/* function types `double (double)' and `double (double, double)', etc. */ - -tree double_ftype_double, double_ftype_double_double; -tree int_ftype_int, long_ftype_long; -tree float_ftype_float; -tree ldouble_ftype_ldouble; - -/* Function type `void (void *, void *, int)' and similar ones */ - -tree void_ftype_ptr_ptr_int, int_ftype_ptr_ptr_int, void_ftype_ptr_int_int; - -/* Function type `char *(char *, char *)' and similar ones */ -tree string_ftype_ptr_ptr, int_ftype_string_string; - -/* Function type `int (const void *, const void *, size_t)' */ -tree int_ftype_cptr_cptr_sizet; - -/* Two expressions that are constants with value zero. - The first is of type `int', the second of type `void *'. */ - -tree integer_zero_node; -tree null_pointer_node; - -/* A node for the integer constant 1. */ - -tree integer_one_node; - -/* Nonzero if we have seen an invalid cross reference - to a struct, union, or enum, but not yet printed the message. */ - -tree pending_invalid_xref; -/* File and line to appear in the eventual error message. */ -char *pending_invalid_xref_file; -int pending_invalid_xref_line; - -/* While defining an enum type, this is 1 plus the last enumerator - constant value. Note that will do not have to save this or `enum_overflow' - around nested function definition since such a definition could only - occur in an enum value expression and we don't use these variables in - that case. */ - -static tree enum_next_value; - -/* Nonzero means that there was overflow computing enum_next_value. */ - -static int enum_overflow; - -/* Parsing a function declarator leaves a list of parameter names - or a chain or parameter decls here. */ - -static tree last_function_parms; - -/* Parsing a function declarator leaves here a chain of structure - and enum types declared in the parmlist. */ - -static tree last_function_parm_tags; - -/* After parsing the declarator that starts a function definition, - `start_function' puts here the list of parameter names or chain of decls. - `store_parm_decls' finds it here. */ - -static tree current_function_parms; - -/* Similar, for last_function_parm_tags. */ -static tree current_function_parm_tags; - -/* Similar, for the file and line that the prototype came from if this is - an old-style definition. */ -static char *current_function_prototype_file; -static int current_function_prototype_line; - -/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function - that have names. Here so we can clear out their names' definitions - at the end of the function. */ - -static tree named_labels; - -/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */ - -static tree shadowed_labels; - -/* Nonzero when store_parm_decls is called indicates a varargs function. - Value not meaningful after store_parm_decls. */ - -static int c_function_varargs; - -/* The FUNCTION_DECL for the function currently being compiled, - or 0 if between functions. */ -tree current_function_decl; - -/* Set to 0 at beginning of a function definition, set to 1 if - a return statement that specifies a return value is seen. */ - -int current_function_returns_value; - -/* Set to 0 at beginning of a function definition, set to 1 if - a return statement with no argument is seen. */ - -int current_function_returns_null; - -/* Set to nonzero by `grokdeclarator' for a function - whose return type is defaulted, if warnings for this are desired. */ - -static int warn_about_return_type; - -/* Nonzero when starting a function declared `extern inline'. */ - -static int current_extern_inline; - -/* For each binding contour we allocate a binding_level structure - * which records the names defined in that contour. - * Contours include: - * 0) the global one - * 1) one for each function definition, - * where internal declarations of the parameters appear. - * 2) one for each compound statement, - * to record its declarations. - * - * The current meaning of a name can be found by searching the levels from - * the current one out to the global one. - */ - -/* Note that the information in the `names' component of the global contour - is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */ - -struct binding_level - { - /* A chain of _DECL nodes for all variables, constants, functions, - and typedef types. These are in the reverse of the order supplied. - */ - tree names; - - /* A list of structure, union and enum definitions, - * for looking up tag names. - * It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name, - * or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE, - * or ENUMERAL_TYPE node. - */ - tree tags; - - /* For each level, a list of shadowed outer-level local definitions - to be restored when this level is popped. - Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and - whose TREE_VALUE is its old definition (a kind of ..._DECL node). */ - tree shadowed; - - /* For each level (except not the global one), - a chain of BLOCK nodes for all the levels - that were entered and exited one level down. */ - tree blocks; - - /* The BLOCK node for this level, if one has been preallocated. - If 0, the BLOCK is allocated (if needed) when the level is popped. */ - tree this_block; - - /* The binding level which this one is contained in (inherits from). */ - struct binding_level *level_chain; - - /* Nonzero for the level that holds the parameters of a function. */ - char parm_flag; - - /* Nonzero if this level "doesn't exist" for tags. */ - char tag_transparent; - - /* Nonzero if sublevels of this level "don't exist" for tags. - This is set in the parm level of a function definition - while reading the function body, so that the outermost block - of the function body will be tag-transparent. */ - char subblocks_tag_transparent; - - /* Nonzero means make a BLOCK for this level regardless of all else. */ - char keep; - - /* Nonzero means make a BLOCK if this level has any subblocks. */ - char keep_if_subblocks; - - /* Number of decls in `names' that have incomplete - structure or union types. */ - int n_incomplete; - - /* A list of decls giving the (reversed) specified order of parms, - not including any forward-decls in the parmlist. - This is so we can put the parms in proper order for assign_parms. */ - tree parm_order; - }; - -#define NULL_BINDING_LEVEL (struct binding_level *) NULL - -/* The binding level currently in effect. */ - -static struct binding_level *current_binding_level; - -/* A chain of binding_level structures awaiting reuse. */ - -static struct binding_level *free_binding_level; - -/* The outermost binding level, for names of file scope. - This is created when the compiler is started and exists - through the entire run. */ - -static struct binding_level *global_binding_level; - -/* Binding level structures are initialized by copying this one. */ - -static struct binding_level clear_binding_level - = {NULL, NULL, NULL, NULL, NULL, NULL_BINDING_LEVEL, 0, 0, 0, 0, 0, 0, - NULL}; - -/* Nonzero means unconditionally make a BLOCK for the next level pushed. */ - -static int keep_next_level_flag; - -/* Nonzero means make a BLOCK for the next level pushed - if it has subblocks. */ - -static int keep_next_if_subblocks; - -/* The chain of outer levels of label scopes. - This uses the same data structure used for binding levels, - but it works differently: each link in the chain records - saved values of named_labels and shadowed_labels for - a label binding level outside the current one. */ - -static struct binding_level *label_level_chain; - -/* Functions called automatically at the beginning and end of execution. */ - -tree static_ctors, static_dtors; - -/* Forward declarations. */ - -static struct binding_level * make_binding_level PROTO((void)); -static void clear_limbo_values PROTO((tree)); -static int duplicate_decls PROTO((tree, tree, int)); -static int redeclaration_error_message PROTO((tree, tree)); -static void storedecls PROTO((tree)); -static void storetags PROTO((tree)); -static tree lookup_tag PROTO((enum tree_code, tree, - struct binding_level *, int)); -static tree lookup_tag_reverse PROTO((tree)); -static tree grokdeclarator PROTO((tree, tree, enum decl_context, - int)); -static tree grokparms PROTO((tree, int)); -static int field_decl_cmp PROTO((const GENERIC_PTR, const GENERIC_PTR)); -static void layout_array_type PROTO((tree)); - -/* C-specific option variables. */ - -/* Nonzero means allow type mismatches in conditional expressions; - just make their values `void'. */ - -int flag_cond_mismatch; - -/* Nonzero means give `double' the same size as `float'. */ - -int flag_short_double; - -/* Nonzero means don't recognize the keyword `asm'. */ - -int flag_no_asm; - -/* Nonzero means don't recognize any builtin functions. */ - -int flag_no_builtin; - -/* Nonzero means don't recognize the non-ANSI builtin functions. - -ansi sets this. */ - -int flag_no_nonansi_builtin; - -/* Nonzero means do some things the same way PCC does. */ - -int flag_traditional; - -/* Nonzero means use the ISO C9x dialect of C. */ - -int flag_isoc9x = 0; - -/* Nonzero means that we have builtin functions, and main is an int */ - -int flag_hosted = 1; - -/* Nonzero means to allow single precision math even if we're generally - being traditional. */ -int flag_allow_single_precision = 0; - -/* Nonzero means to treat bitfields as signed unless they say `unsigned'. */ - -int flag_signed_bitfields = 1; -int explicit_flag_signed_bitfields = 0; - -/* Nonzero means warn about use of implicit int. */ - -int warn_implicit_int; - -/* Nonzero means warn about usage of long long when `-pedantic'. */ - -int warn_long_long = 1; - -/* Nonzero means message about use of implicit function declarations; - 1 means warning; 2 means error. */ - -int mesg_implicit_function_declaration; - -/* Nonzero means give string constants the type `const char *' - to get extra warnings from them. These warnings will be too numerous - to be useful, except in thoroughly ANSIfied programs. */ - -int flag_const_strings; - -/* Nonzero means warn about pointer casts that can drop a type qualifier - from the pointer target type. */ - -int warn_cast_qual; - -/* Nonzero means warn when casting a function call to a type that does - not match the return type (e.g. (float)sqrt() or (anything*)malloc() - when there is no previous declaration of sqrt or malloc. */ - -int warn_bad_function_cast; - -/* Warn about functions which might be candidates for attribute noreturn. */ - -int warn_missing_noreturn; - -/* Warn about traditional constructs whose meanings changed in ANSI C. */ - -int warn_traditional; - -/* Nonzero means warn about sizeof(function) or addition/subtraction - of function pointers. */ - -int warn_pointer_arith; - -/* Nonzero means warn for non-prototype function decls - or non-prototyped defs without previous prototype. */ - -int warn_strict_prototypes; - -/* Nonzero means warn for any global function def - without separate previous prototype decl. */ - -int warn_missing_prototypes; - -/* Nonzero means warn for any global function def - without separate previous decl. */ - -int warn_missing_declarations; - -/* Nonzero means warn about multiple (redundant) decls for the same single - variable or function. */ - -int warn_redundant_decls = 0; - -/* Nonzero means warn about extern declarations of objects not at - file-scope level and about *all* declarations of functions (whether - extern or static) not at file-scope level. Note that we exclude - implicit function declarations. To get warnings about those, use - -Wimplicit. */ - -int warn_nested_externs = 0; - -/* Warn about *printf or *scanf format/argument anomalies. */ - -int warn_format; - -/* Warn about a subscript that has type char. */ - -int warn_char_subscripts = 0; - -/* Warn if a type conversion is done that might have confusing results. */ - -int warn_conversion; - -/* Warn if adding () is suggested. */ - -int warn_parentheses; - -/* Warn if initializer is not completely bracketed. */ - -int warn_missing_braces; - -/* Warn if main is suspicious. */ - -int warn_main; - -/* Warn about #pragma directives that are not recognised. */ - -int warn_unknown_pragmas = 0; /* Tri state variable. */ - -/* Warn about comparison of signed and unsigned values. - If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified. */ - -int warn_sign_compare = -1; - -/* Nonzero means warn about use of multicharacter literals. */ - -int warn_multichar = 1; - -/* Nonzero means `$' can be in an identifier. */ - -#ifndef DOLLARS_IN_IDENTIFIERS -#define DOLLARS_IN_IDENTIFIERS 1 -#endif -int dollars_in_ident = DOLLARS_IN_IDENTIFIERS; - -/* Decode the string P as a language-specific option for C. - Return the number of strings consumed. */ - -int -c_decode_option (argc, argv) - int argc ATTRIBUTE_UNUSED; - char **argv; -{ - int strings_processed; - char *p = argv[0]; -#if USE_CPPLIB - strings_processed = cpp_handle_option (&parse_in, argc, argv); -#else - strings_processed = 0; -#endif /* ! USE_CPPLIB */ - - if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional")) - { - flag_traditional = 1; - flag_writable_strings = 1; - } - else if (!strcmp (p, "-fallow-single-precision")) - flag_allow_single_precision = 1; - else if (!strcmp (p, "-fhosted") || !strcmp (p, "-fno-freestanding")) - { - flag_hosted = 1; - flag_no_builtin = 0; - } - else if (!strcmp (p, "-ffreestanding") || !strcmp (p, "-fno-hosted")) - { - flag_hosted = 0; - flag_no_builtin = 1; - /* warn_main will be 2 if set by -Wall, 1 if set by -Wmain */ - if (warn_main == 2) - warn_main = 0; - } - else if (!strcmp (p, "-fnotraditional") || !strcmp (p, "-fno-traditional")) - { - flag_traditional = 0; - flag_writable_strings = 0; - } - else if (!strncmp (p, "-std=", 5)) - { - /* Select the appropriate language standard. We currently - recognize: - -std=iso9899:1990 same as -ansi - -std=iso9899:199409 ISO C as modified in amend. 1 - -std=iso9899:199x ISO C 9x - -std=c89 same as -std=iso9899:1990 - -std=c9x same as -std=iso9899:199x - -std=gnu89 default, iso9899:1990 + gnu extensions - -std=gnu9x iso9899:199x + gnu extensions - */ - const char *argstart = &p[5]; - - if (!strcmp (argstart, "iso9899:1990") - || !strcmp (argstart, "c89")) - { - iso_1990: - flag_traditional = 0; - flag_writable_strings = 0; - flag_no_asm = 1; - flag_no_nonansi_builtin = 1; - flag_isoc9x = 0; - } - else if (!strcmp (argstart, "iso9899:199409")) - { - /* ??? The changes since ISO C 1990 are not supported. */ - goto iso_1990; - } - else if (!strcmp (argstart, "iso9899:199x") - || !strcmp (argstart, "c9x")) - { - flag_traditional = 0; - flag_writable_strings = 0; - flag_no_asm = 1; - flag_no_nonansi_builtin = 1; - flag_isoc9x = 1; - } - else if (!strcmp (argstart, "gnu89")) - { - flag_traditional = 0; - flag_writable_strings = 0; - flag_no_asm = 0; - flag_no_nonansi_builtin = 0; - flag_isoc9x = 0; - } - else if (!strcmp (argstart, "gnu9x")) - { - flag_traditional = 0; - flag_writable_strings = 0; - flag_no_asm = 0; - flag_no_nonansi_builtin = 0; - flag_isoc9x = 1; - } - else - error ("unknown C standard `%s'", argstart); - } - else if (!strcmp (p, "-fdollars-in-identifiers")) - dollars_in_ident = 1; - else if (!strcmp (p, "-fno-dollars-in-identifiers")) - dollars_in_ident = 0; - else if (!strcmp (p, "-fsigned-char")) - flag_signed_char = 1; - else if (!strcmp (p, "-funsigned-char")) - flag_signed_char = 0; - else if (!strcmp (p, "-fno-signed-char")) - flag_signed_char = 0; - else if (!strcmp (p, "-fno-unsigned-char")) - flag_signed_char = 1; - else if (!strcmp (p, "-fsigned-bitfields") - || !strcmp (p, "-fno-unsigned-bitfields")) - { - flag_signed_bitfields = 1; - explicit_flag_signed_bitfields = 1; - } - else if (!strcmp (p, "-funsigned-bitfields") - || !strcmp (p, "-fno-signed-bitfields")) - { - flag_signed_bitfields = 0; - explicit_flag_signed_bitfields = 1; - } - else if (!strcmp (p, "-fshort-enums")) - flag_short_enums = 1; - else if (!strcmp (p, "-fno-short-enums")) - flag_short_enums = 0; - else if (!strcmp (p, "-fcond-mismatch")) - flag_cond_mismatch = 1; - else if (!strcmp (p, "-fno-cond-mismatch")) - flag_cond_mismatch = 0; - else if (!strcmp (p, "-fshort-double")) - flag_short_double = 1; - else if (!strcmp (p, "-fno-short-double")) - flag_short_double = 0; - else if (!strcmp (p, "-fasm")) - flag_no_asm = 0; - else if (!strcmp (p, "-fno-asm")) - flag_no_asm = 1; - else if (!strcmp (p, "-fbuiltin")) - flag_no_builtin = 0; - else if (!strcmp (p, "-fno-builtin")) - flag_no_builtin = 1; - else if (!strcmp (p, "-ansi")) - goto iso_1990; - else if (!strcmp (p, "-Werror-implicit-function-declaration")) - mesg_implicit_function_declaration = 2; - else if (!strcmp (p, "-Wimplicit-function-declaration")) - mesg_implicit_function_declaration = 1; - else if (!strcmp (p, "-Wno-implicit-function-declaration")) - mesg_implicit_function_declaration = 0; - else if (!strcmp (p, "-Wimplicit-int")) - warn_implicit_int = 1; - else if (!strcmp (p, "-Wno-implicit-int")) - warn_implicit_int = 0; - else if (!strcmp (p, "-Wimplicit")) - { - warn_implicit_int = 1; - if (mesg_implicit_function_declaration != 2) - mesg_implicit_function_declaration = 1; - } - else if (!strcmp (p, "-Wno-implicit")) - warn_implicit_int = 0, mesg_implicit_function_declaration = 0; - else if (!strcmp (p, "-Wlong-long")) - warn_long_long = 1; - else if (!strcmp (p, "-Wno-long-long")) - warn_long_long = 0; - else if (!strcmp (p, "-Wwrite-strings")) - flag_const_strings = 1; - else if (!strcmp (p, "-Wno-write-strings")) - flag_const_strings = 0; - else if (!strcmp (p, "-Wcast-qual")) - warn_cast_qual = 1; - else if (!strcmp (p, "-Wno-cast-qual")) - warn_cast_qual = 0; - else if (!strcmp (p, "-Wbad-function-cast")) - warn_bad_function_cast = 1; - else if (!strcmp (p, "-Wno-bad-function-cast")) - warn_bad_function_cast = 0; - else if (!strcmp (p, "-Wmissing-noreturn")) - warn_missing_noreturn = 1; - else if (!strcmp (p, "-Wno-missing-noreturn")) - warn_missing_noreturn = 0; - else if (!strcmp (p, "-Wpointer-arith")) - warn_pointer_arith = 1; - else if (!strcmp (p, "-Wno-pointer-arith")) - warn_pointer_arith = 0; - else if (!strcmp (p, "-Wstrict-prototypes")) - warn_strict_prototypes = 1; - else if (!strcmp (p, "-Wno-strict-prototypes")) - warn_strict_prototypes = 0; - else if (!strcmp (p, "-Wmissing-prototypes")) - warn_missing_prototypes = 1; - else if (!strcmp (p, "-Wno-missing-prototypes")) - warn_missing_prototypes = 0; - else if (!strcmp (p, "-Wmissing-declarations")) - warn_missing_declarations = 1; - else if (!strcmp (p, "-Wno-missing-declarations")) - warn_missing_declarations = 0; - else if (!strcmp (p, "-Wredundant-decls")) - warn_redundant_decls = 1; - else if (!strcmp (p, "-Wno-redundant-decls")) - warn_redundant_decls = 0; - else if (!strcmp (p, "-Wnested-externs")) - warn_nested_externs = 1; - else if (!strcmp (p, "-Wno-nested-externs")) - warn_nested_externs = 0; - else if (!strcmp (p, "-Wtraditional")) - warn_traditional = 1; - else if (!strcmp (p, "-Wno-traditional")) - warn_traditional = 0; - else if (!strcmp (p, "-Wformat")) - warn_format = 1; - else if (!strcmp (p, "-Wno-format")) - warn_format = 0; - else if (!strcmp (p, "-Wchar-subscripts")) - warn_char_subscripts = 1; - else if (!strcmp (p, "-Wno-char-subscripts")) - warn_char_subscripts = 0; - else if (!strcmp (p, "-Wconversion")) - warn_conversion = 1; - else if (!strcmp (p, "-Wno-conversion")) - warn_conversion = 0; - else if (!strcmp (p, "-Wparentheses")) - warn_parentheses = 1; - else if (!strcmp (p, "-Wno-parentheses")) - warn_parentheses = 0; - else if (!strcmp (p, "-Wreturn-type")) - warn_return_type = 1; - else if (!strcmp (p, "-Wno-return-type")) - warn_return_type = 0; - else if (!strcmp (p, "-Wcomment")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-comment")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wcomments")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-comments")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wtrigraphs")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-trigraphs")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wundef")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-undef")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wimport")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-import")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wmissing-braces")) - warn_missing_braces = 1; - else if (!strcmp (p, "-Wno-missing-braces")) - warn_missing_braces = 0; - else if (!strcmp (p, "-Wmain")) - warn_main = 1; - else if (!strcmp (p, "-Wno-main")) - warn_main = -1; - else if (!strcmp (p, "-Wsign-compare")) - warn_sign_compare = 1; - else if (!strcmp (p, "-Wno-sign-compare")) - warn_sign_compare = 0; - else if (!strcmp (p, "-Wmultichar")) - warn_multichar = 1; - else if (!strcmp (p, "-Wno-multichar")) - warn_multichar = 0; - else if (!strcmp (p, "-Wunknown-pragmas")) - /* Set to greater than 1, so that even unknown pragmas in system - headers will be warned about. */ - warn_unknown_pragmas = 2; - else if (!strcmp (p, "-Wno-unknown-pragmas")) - warn_unknown_pragmas = 0; - else if (!strcmp (p, "-Wall")) - { - /* We save the value of warn_uninitialized, since if they put - -Wuninitialized on the command line, we need to generate a - warning about not using it without also specifying -O. */ - if (warn_uninitialized != 1) - warn_uninitialized = 2; - warn_implicit_int = 1; - mesg_implicit_function_declaration = 1; - warn_return_type = 1; - warn_unused = 1; - warn_switch = 1; - warn_format = 1; - warn_char_subscripts = 1; - warn_parentheses = 1; - warn_missing_braces = 1; - /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding can turn - it off only if it's not explicit. */ - warn_main = 2; - /* Only warn about unknown pragmas that are not in system headers. */ - warn_unknown_pragmas = 1; - } - else - return strings_processed; - - return 1; -} - -/* Hooks for print_node. */ - -void -print_lang_decl (file, node, indent) - FILE *file ATTRIBUTE_UNUSED; - tree node ATTRIBUTE_UNUSED; - int indent ATTRIBUTE_UNUSED; -{ -} - -void -print_lang_type (file, node, indent) - FILE *file ATTRIBUTE_UNUSED; - tree node ATTRIBUTE_UNUSED; - int indent ATTRIBUTE_UNUSED; -{ -} - -void -print_lang_identifier (file, node, indent) - FILE *file; - tree node; - int indent; -{ - print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4); - print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4); - print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4); - print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4); - print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4); - print_node (file, "limbo value", IDENTIFIER_LIMBO_VALUE (node), indent + 4); -} - -/* Hook called at end of compilation to assume 1 elt - for a top-level array decl that wasn't complete before. */ - -void -finish_incomplete_decl (decl) - tree decl; -{ - if (TREE_CODE (decl) == VAR_DECL) - { - tree type = TREE_TYPE (decl); - if (type != error_mark_node - && TREE_CODE (type) == ARRAY_TYPE - && TYPE_DOMAIN (type) == 0) - { - if (! DECL_EXTERNAL (decl)) - warning_with_decl (decl, "array `%s' assumed to have one element"); - - complete_array_type (type, NULL_TREE, 1); - - layout_decl (decl, 0); - } - } -} - -/* Create a new `struct binding_level'. */ - -static -struct binding_level * -make_binding_level () -{ - /* NOSTRICT */ - return (struct binding_level *) xmalloc (sizeof (struct binding_level)); -} - -/* Nonzero if we are currently in the global binding level. */ - -int -global_bindings_p () -{ - return current_binding_level == global_binding_level; -} - -void -keep_next_level () -{ - keep_next_level_flag = 1; -} - -/* Nonzero if the current level needs to have a BLOCK made. */ - -int -kept_level_p () -{ - return ((current_binding_level->keep_if_subblocks - && current_binding_level->blocks != 0) - || current_binding_level->keep - || current_binding_level->names != 0 - || (current_binding_level->tags != 0 - && !current_binding_level->tag_transparent)); -} - -/* Identify this binding level as a level of parameters. - DEFINITION_FLAG is 1 for a definition, 0 for a declaration. - But it turns out there is no way to pass the right value for - DEFINITION_FLAG, so we ignore it. */ - -void -declare_parm_level (definition_flag) - int definition_flag ATTRIBUTE_UNUSED; -{ - current_binding_level->parm_flag = 1; -} - -/* Nonzero if currently making parm declarations. */ - -int -in_parm_level_p () -{ - return current_binding_level->parm_flag; -} - -/* Enter a new binding level. - If TAG_TRANSPARENT is nonzero, do so only for the name space of variables, - not for that of tags. */ - -void -pushlevel (tag_transparent) - int tag_transparent; -{ - register struct binding_level *newlevel = NULL_BINDING_LEVEL; - - /* If this is the top level of a function, - just make sure that NAMED_LABELS is 0. */ - - if (current_binding_level == global_binding_level) - { - named_labels = 0; - } - - /* Reuse or create a struct for this binding level. */ - - if (free_binding_level) - { - newlevel = free_binding_level; - free_binding_level = free_binding_level->level_chain; - } - else - { - newlevel = make_binding_level (); - } - - /* Add this level to the front of the chain (stack) of levels that - are active. */ - - *newlevel = clear_binding_level; - newlevel->tag_transparent - = (tag_transparent - || (current_binding_level - ? current_binding_level->subblocks_tag_transparent - : 0)); - newlevel->level_chain = current_binding_level; - current_binding_level = newlevel; - newlevel->keep = keep_next_level_flag; - keep_next_level_flag = 0; - newlevel->keep_if_subblocks = keep_next_if_subblocks; - keep_next_if_subblocks = 0; -} - -/* Clear the limbo values of all identifiers defined in BLOCK or a subblock. */ - -static void -clear_limbo_values (block) - tree block; -{ - tree tem; - - for (tem = BLOCK_VARS (block); tem; tem = TREE_CHAIN (tem)) - if (DECL_NAME (tem) != 0) - IDENTIFIER_LIMBO_VALUE (DECL_NAME (tem)) = 0; - - for (tem = BLOCK_SUBBLOCKS (block); tem; tem = TREE_CHAIN (tem)) - clear_limbo_values (tem); -} - -/* Exit a binding level. - Pop the level off, and restore the state of the identifier-decl mappings - that were in effect when this level was entered. - - If KEEP is nonzero, this level had explicit declarations, so - and create a "block" (a BLOCK node) for the level - to record its declarations and subblocks for symbol table output. - - If FUNCTIONBODY is nonzero, this level is the body of a function, - so create a block as if KEEP were set and also clear out all - label names. - - If REVERSE is nonzero, reverse the order of decls before putting - them into the BLOCK. */ - -tree -poplevel (keep, reverse, functionbody) - int keep; - int reverse; - int functionbody; -{ - register tree link; - /* The chain of decls was accumulated in reverse order. - Put it into forward order, just for cleanliness. */ - tree decls; - tree tags = current_binding_level->tags; - tree subblocks = current_binding_level->blocks; - tree block = 0; - tree decl; - int block_previously_created; - - keep |= current_binding_level->keep; - - /* This warning is turned off because it causes warnings for - declarations like `extern struct foo *x'. */ -#if 0 - /* Warn about incomplete structure types in this level. */ - for (link = tags; link; link = TREE_CHAIN (link)) - if (TYPE_SIZE (TREE_VALUE (link)) == 0) - { - tree type = TREE_VALUE (link); - tree type_name = TYPE_NAME (type); - char *id = IDENTIFIER_POINTER (TREE_CODE (type_name) == IDENTIFIER_NODE - ? type_name - : DECL_NAME (type_name)); - switch (TREE_CODE (type)) - { - case RECORD_TYPE: - error ("`struct %s' incomplete in scope ending here", id); - break; - case UNION_TYPE: - error ("`union %s' incomplete in scope ending here", id); - break; - case ENUMERAL_TYPE: - error ("`enum %s' incomplete in scope ending here", id); - break; - } - } -#endif /* 0 */ - - /* Get the decls in the order they were written. - Usually current_binding_level->names is in reverse order. - But parameter decls were previously put in forward order. */ - - if (reverse) - current_binding_level->names - = decls = nreverse (current_binding_level->names); - else - decls = current_binding_level->names; - - /* Output any nested inline functions within this block - if they weren't already output. */ - - for (decl = decls; decl; decl = TREE_CHAIN (decl)) - if (TREE_CODE (decl) == FUNCTION_DECL - && ! TREE_ASM_WRITTEN (decl) - && DECL_INITIAL (decl) != 0 - && TREE_ADDRESSABLE (decl)) - { - /* If this decl was copied from a file-scope decl - on account of a block-scope extern decl, - propagate TREE_ADDRESSABLE to the file-scope decl. - - DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is - true, since then the decl goes through save_for_inline_copying. */ - if (DECL_ABSTRACT_ORIGIN (decl) != 0 - && DECL_ABSTRACT_ORIGIN (decl) != decl) - TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1; - else if (DECL_SAVED_INSNS (decl) != 0) - { - push_function_context (); - output_inline_function (decl); - pop_function_context (); - } - } - - /* If there were any declarations or structure tags in that level, - or if this level is a function body, - create a BLOCK to record them for the life of this function. */ - - block = 0; - block_previously_created = (current_binding_level->this_block != 0); - if (block_previously_created) - block = current_binding_level->this_block; - else if (keep || functionbody - || (current_binding_level->keep_if_subblocks && subblocks != 0)) - block = make_node (BLOCK); - if (block != 0) - { - BLOCK_VARS (block) = decls; - BLOCK_TYPE_TAGS (block) = tags; - BLOCK_SUBBLOCKS (block) = subblocks; - remember_end_note (block); - } - - /* In each subblock, record that this is its superior. */ - - for (link = subblocks; link; link = TREE_CHAIN (link)) - BLOCK_SUPERCONTEXT (link) = block; - - /* Clear out the meanings of the local variables of this level. */ - - for (link = decls; link; link = TREE_CHAIN (link)) - { - if (DECL_NAME (link) != 0) - { - /* If the ident. was used or addressed via a local extern decl, - don't forget that fact. */ - if (DECL_EXTERNAL (link)) - { - if (TREE_USED (link)) - TREE_USED (DECL_NAME (link)) = 1; - if (TREE_ADDRESSABLE (link)) - TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1; - } - IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0; - } - } - - /* Restore all name-meanings of the outer levels - that were shadowed by this level. */ - - for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) - IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); - - /* If the level being exited is the top level of a function, - check over all the labels, and clear out the current - (function local) meanings of their names. */ - - if (functionbody) - { - clear_limbo_values (block); - - /* If this is the top level block of a function, - the vars are the function's parameters. - Don't leave them in the BLOCK because they are - found in the FUNCTION_DECL instead. */ - - BLOCK_VARS (block) = 0; - - /* Clear out the definitions of all label names, - since their scopes end here, - and add them to BLOCK_VARS. */ - - for (link = named_labels; link; link = TREE_CHAIN (link)) - { - register tree label = TREE_VALUE (link); - - if (DECL_INITIAL (label) == 0) - { - error_with_decl (label, "label `%s' used but not defined"); - /* Avoid crashing later. */ - define_label (input_filename, lineno, - DECL_NAME (label)); - } - else if (warn_unused && !TREE_USED (label)) - warning_with_decl (label, "label `%s' defined but not used"); - IDENTIFIER_LABEL_VALUE (DECL_NAME (label)) = 0; - - /* Put the labels into the "variables" of the - top-level block, so debugger can see them. */ - TREE_CHAIN (label) = BLOCK_VARS (block); - BLOCK_VARS (block) = label; - } - } - - /* Pop the current level, and free the structure for reuse. */ - - { - register struct binding_level *level = current_binding_level; - current_binding_level = current_binding_level->level_chain; - - level->level_chain = free_binding_level; - free_binding_level = level; - } - - /* Dispose of the block that we just made inside some higher level. */ - if (functionbody) - DECL_INITIAL (current_function_decl) = block; - else if (block) - { - if (!block_previously_created) - current_binding_level->blocks - = chainon (current_binding_level->blocks, block); - } - /* If we did not make a block for the level just exited, - any blocks made for inner levels - (since they cannot be recorded as subblocks in that level) - must be carried forward so they will later become subblocks - of something else. */ - else if (subblocks) - current_binding_level->blocks - = chainon (current_binding_level->blocks, subblocks); - - /* Set the TYPE_CONTEXTs for all of the tagged types belonging to this - binding contour so that they point to the appropriate construct, i.e. - either to the current FUNCTION_DECL node, or else to the BLOCK node - we just constructed. - - Note that for tagged types whose scope is just the formal parameter - list for some function type specification, we can't properly set - their TYPE_CONTEXTs here, because we don't have a pointer to the - appropriate FUNCTION_TYPE node readily available to us. For those - cases, the TYPE_CONTEXTs of the relevant tagged type nodes get set - in `grokdeclarator' as soon as we have created the FUNCTION_TYPE - node which will represent the "scope" for these "parameter list local" - tagged types. - */ - - if (functionbody) - for (link = tags; link; link = TREE_CHAIN (link)) - TYPE_CONTEXT (TREE_VALUE (link)) = current_function_decl; - else if (block) - for (link = tags; link; link = TREE_CHAIN (link)) - TYPE_CONTEXT (TREE_VALUE (link)) = block; - - if (block) - TREE_USED (block) = 1; - return block; -} - -/* Delete the node BLOCK from the current binding level. - This is used for the block inside a stmt expr ({...}) - so that the block can be reinserted where appropriate. */ - -void -delete_block (block) - tree block; -{ - tree t; - if (current_binding_level->blocks == block) - current_binding_level->blocks = TREE_CHAIN (block); - for (t = current_binding_level->blocks; t;) - { - if (TREE_CHAIN (t) == block) - TREE_CHAIN (t) = TREE_CHAIN (block); - else - t = TREE_CHAIN (t); - } - TREE_CHAIN (block) = NULL; - /* Clear TREE_USED which is always set by poplevel. - The flag is set again if insert_block is called. */ - TREE_USED (block) = 0; -} - -/* Insert BLOCK at the end of the list of subblocks of the - current binding level. This is used when a BIND_EXPR is expanded, - to handle the BLOCK node inside the BIND_EXPR. */ - -void -insert_block (block) - tree block; -{ - TREE_USED (block) = 1; - current_binding_level->blocks - = chainon (current_binding_level->blocks, block); -} - -/* Set the BLOCK node for the innermost scope - (the one we are currently in). */ - -void -set_block (block) - register tree block; -{ - current_binding_level->this_block = block; -} - -void -push_label_level () -{ - register struct binding_level *newlevel; - - /* Reuse or create a struct for this binding level. */ - - if (free_binding_level) - { - newlevel = free_binding_level; - free_binding_level = free_binding_level->level_chain; - } - else - { - newlevel = make_binding_level (); - } - - /* Add this level to the front of the chain (stack) of label levels. */ - - newlevel->level_chain = label_level_chain; - label_level_chain = newlevel; - - newlevel->names = named_labels; - newlevel->shadowed = shadowed_labels; - named_labels = 0; - shadowed_labels = 0; -} - -void -pop_label_level () -{ - register struct binding_level *level = label_level_chain; - tree link, prev; - - /* Clear out the definitions of the declared labels in this level. - Leave in the list any ordinary, non-declared labels. */ - for (link = named_labels, prev = 0; link;) - { - if (C_DECLARED_LABEL_FLAG (TREE_VALUE (link))) - { - if (DECL_SOURCE_LINE (TREE_VALUE (link)) == 0) - { - error_with_decl (TREE_VALUE (link), - "label `%s' used but not defined"); - /* Avoid crashing later. */ - define_label (input_filename, lineno, - DECL_NAME (TREE_VALUE (link))); - } - else if (warn_unused && !TREE_USED (TREE_VALUE (link))) - warning_with_decl (TREE_VALUE (link), - "label `%s' defined but not used"); - IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link))) = 0; - - /* Delete this element from the list. */ - link = TREE_CHAIN (link); - if (prev) - TREE_CHAIN (prev) = link; - else - named_labels = link; - } - else - { - prev = link; - link = TREE_CHAIN (link); - } - } - - /* Bring back all the labels that were shadowed. */ - for (link = shadowed_labels; link; link = TREE_CHAIN (link)) - if (DECL_NAME (TREE_VALUE (link)) != 0) - IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link))) - = TREE_VALUE (link); - - named_labels = chainon (named_labels, level->names); - shadowed_labels = level->shadowed; - - /* Pop the current level, and free the structure for reuse. */ - label_level_chain = label_level_chain->level_chain; - level->level_chain = free_binding_level; - free_binding_level = level; -} - -/* Push a definition or a declaration of struct, union or enum tag "name". - "type" should be the type node. - We assume that the tag "name" is not already defined. - - Note that the definition may really be just a forward reference. - In that case, the TYPE_SIZE will be zero. */ - -void -pushtag (name, type) - tree name, type; -{ - register struct binding_level *b; - - /* Find the proper binding level for this type tag. */ - - for (b = current_binding_level; b->tag_transparent; b = b->level_chain) - continue; - - if (name) - { - /* Record the identifier as the type's name if it has none. */ - - if (TYPE_NAME (type) == 0) - TYPE_NAME (type) = name; - } - - if (b == global_binding_level) - b->tags = perm_tree_cons (name, type, b->tags); - else - b->tags = saveable_tree_cons (name, type, b->tags); - - /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the - tagged type we just added to the current binding level. This fake - NULL-named TYPE_DECL node helps dwarfout.c to know when it needs - to output a representation of a tagged type, and it also gives - us a convenient place to record the "scope start" address for the - tagged type. */ - - TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type)); - - /* An approximation for now, so we can tell this is a function-scope tag. - This will be updated in poplevel. */ - TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type)); -} - -/* Handle when a new declaration NEWDECL - has the same name as an old one OLDDECL - in the same binding contour. - Prints an error message if appropriate. - - If safely possible, alter OLDDECL to look like NEWDECL, and return 1. - Otherwise, return 0. - - When DIFFERENT_BINDING_LEVEL is true, NEWDECL is an external declaration, - and OLDDECL is in an outer binding level and should thus not be changed. */ - -static int -duplicate_decls (newdecl, olddecl, different_binding_level) - register tree newdecl, olddecl; - int different_binding_level; -{ - int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); - int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL - && DECL_INITIAL (newdecl) != 0); - tree oldtype = TREE_TYPE (olddecl); - tree newtype = TREE_TYPE (newdecl); - int errmsg = 0; - - if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd') - DECL_MACHINE_ATTRIBUTES (newdecl) - = merge_machine_decl_attributes (olddecl, newdecl); - - if (TREE_CODE (newtype) == ERROR_MARK - || TREE_CODE (oldtype) == ERROR_MARK) - types_match = 0; - - /* New decl is completely inconsistent with the old one => - tell caller to replace the old one. - This is always an error except in the case of shadowing a builtin. */ - if (TREE_CODE (olddecl) != TREE_CODE (newdecl)) - { - if (TREE_CODE (olddecl) == FUNCTION_DECL - && (DECL_BUILT_IN (olddecl) - || DECL_BUILT_IN_NONANSI (olddecl))) - { - /* If you declare a built-in or predefined function name as static, - the old definition is overridden, - but optionally warn this was a bad choice of name. */ - if (!TREE_PUBLIC (newdecl)) - { - if (!warn_shadow) - ; - else if (DECL_BUILT_IN (olddecl)) - warning_with_decl (newdecl, "shadowing built-in function `%s'"); - else - warning_with_decl (newdecl, "shadowing library function `%s'"); - } - /* Likewise, if the built-in is not ansi, then programs can - override it even globally without an error. */ - else if (! DECL_BUILT_IN (olddecl)) - warning_with_decl (newdecl, - "library function `%s' declared as non-function"); - - else if (DECL_BUILT_IN_NONANSI (olddecl)) - warning_with_decl (newdecl, - "built-in function `%s' declared as non-function"); - else - warning_with_decl (newdecl, - "built-in function `%s' declared as non-function"); - } - else - { - error_with_decl (newdecl, "`%s' redeclared as different kind of symbol"); - error_with_decl (olddecl, "previous declaration of `%s'"); - } - - return 0; - } - - /* For real parm decl following a forward decl, - return 1 so old decl will be reused. */ - if (types_match && TREE_CODE (newdecl) == PARM_DECL - && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl)) - return 1; - - /* The new declaration is the same kind of object as the old one. - The declarations may partially match. Print warnings if they don't - match enough. Ultimately, copy most of the information from the new - decl to the old one, and keep using the old one. */ - - if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL - && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (newdecl)) == olddecl - && DECL_INITIAL (olddecl) == 0) - /* If -traditional, avoid error for redeclaring fcn - after implicit decl. */ - ; - else if (TREE_CODE (olddecl) == FUNCTION_DECL - && DECL_BUILT_IN (olddecl)) - { - /* A function declaration for a built-in function. */ - if (!TREE_PUBLIC (newdecl)) - { - /* If you declare a built-in function name as static, the - built-in definition is overridden, - but optionally warn this was a bad choice of name. */ - if (warn_shadow) - warning_with_decl (newdecl, "shadowing built-in function `%s'"); - /* Discard the old built-in function. */ - return 0; - } - else if (!types_match) - { - /* Accept the return type of the new declaration if same modes. */ - tree oldreturntype = TREE_TYPE (oldtype); - tree newreturntype = TREE_TYPE (newtype); - - /* Make sure we put the new type in the same obstack as the old ones. - If the old types are not both in the same obstack, use the - permanent one. */ - if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype)) - push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype)); - else - { - push_obstacks_nochange (); - end_temporary_allocation (); - } - - if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype)) - { - /* Function types may be shared, so we can't just modify - the return type of olddecl's function type. */ - tree trytype - = build_function_type (newreturntype, - TYPE_ARG_TYPES (oldtype)); - - types_match = comptypes (newtype, trytype); - if (types_match) - oldtype = trytype; - } - /* Accept harmless mismatch in first argument type also. - This is for ffs. */ - if (TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0 - && TYPE_ARG_TYPES (oldtype) != 0 - && TREE_VALUE (TYPE_ARG_TYPES (newtype)) != 0 - && TREE_VALUE (TYPE_ARG_TYPES (oldtype)) != 0 - && (TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (newtype))) - == TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (oldtype))))) - { - /* Function types may be shared, so we can't just modify - the return type of olddecl's function type. */ - tree trytype - = build_function_type (TREE_TYPE (oldtype), - tree_cons (NULL_TREE, - TREE_VALUE (TYPE_ARG_TYPES (newtype)), - TREE_CHAIN (TYPE_ARG_TYPES (oldtype)))); - - types_match = comptypes (newtype, trytype); - if (types_match) - oldtype = trytype; - } - if (! different_binding_level) - TREE_TYPE (olddecl) = oldtype; - - pop_obstacks (); - } - if (!types_match) - { - /* If types don't match for a built-in, throw away the built-in. */ - warning_with_decl (newdecl, "conflicting types for built-in function `%s'"); - return 0; - } - } - else if (TREE_CODE (olddecl) == FUNCTION_DECL - && DECL_SOURCE_LINE (olddecl) == 0) - { - /* A function declaration for a predeclared function - that isn't actually built in. */ - if (!TREE_PUBLIC (newdecl)) - { - /* If you declare it as static, the - default definition is overridden. */ - return 0; - } - else if (!types_match) - { - /* If the types don't match, preserve volatility indication. - Later on, we will discard everything else about the - default declaration. */ - TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl); - } - } - /* Permit char *foo () to match void *foo (...) if not pedantic, - if one of them came from a system header file. */ - else if (!types_match - && TREE_CODE (olddecl) == FUNCTION_DECL - && TREE_CODE (newdecl) == FUNCTION_DECL - && TREE_CODE (TREE_TYPE (oldtype)) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (newtype)) == POINTER_TYPE - && (DECL_IN_SYSTEM_HEADER (olddecl) - || DECL_IN_SYSTEM_HEADER (newdecl)) - && ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (newtype))) == void_type_node - && TYPE_ARG_TYPES (oldtype) == 0 - && self_promoting_args_p (TYPE_ARG_TYPES (newtype)) - && TREE_TYPE (TREE_TYPE (oldtype)) == char_type_node) - || - (TREE_TYPE (TREE_TYPE (newtype)) == char_type_node - && TYPE_ARG_TYPES (newtype) == 0 - && self_promoting_args_p (TYPE_ARG_TYPES (oldtype)) - && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (oldtype))) == void_type_node))) - { - if (pedantic) - pedwarn_with_decl (newdecl, "conflicting types for `%s'"); - /* Make sure we keep void * as ret type, not char *. */ - if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (oldtype))) == void_type_node) - TREE_TYPE (newdecl) = newtype = oldtype; - - /* Set DECL_IN_SYSTEM_HEADER, so that if we see another declaration - we will come back here again. */ - DECL_IN_SYSTEM_HEADER (newdecl) = 1; - } - else if (!types_match - /* Permit char *foo (int, ...); followed by char *foo (); - if not pedantic. */ - && ! (TREE_CODE (olddecl) == FUNCTION_DECL - && ! pedantic - /* Return types must still match. */ - && comptypes (TREE_TYPE (oldtype), - TREE_TYPE (newtype)) - && TYPE_ARG_TYPES (newtype) == 0)) - { - error_with_decl (newdecl, "conflicting types for `%s'"); - /* Check for function type mismatch - involving an empty arglist vs a nonempty one. */ - if (TREE_CODE (olddecl) == FUNCTION_DECL - && comptypes (TREE_TYPE (oldtype), - TREE_TYPE (newtype)) - && ((TYPE_ARG_TYPES (oldtype) == 0 - && DECL_INITIAL (olddecl) == 0) - || - (TYPE_ARG_TYPES (newtype) == 0 - && DECL_INITIAL (newdecl) == 0))) - { - /* Classify the problem further. */ - register tree t = TYPE_ARG_TYPES (oldtype); - if (t == 0) - t = TYPE_ARG_TYPES (newtype); - for (; t; t = TREE_CHAIN (t)) - { - register tree type = TREE_VALUE (t); - - if (TREE_CHAIN (t) == 0 - && TYPE_MAIN_VARIANT (type) != void_type_node) - { - error ("A parameter list with an ellipsis can't match an empty parameter name list declaration."); - break; - } - - if (TYPE_MAIN_VARIANT (type) == float_type_node - || C_PROMOTING_INTEGER_TYPE_P (type)) - { - error ("An argument type that has a default promotion can't match an empty parameter name list declaration."); - break; - } - } - } - error_with_decl (olddecl, "previous declaration of `%s'"); - } - else - { - errmsg = redeclaration_error_message (newdecl, olddecl); - if (errmsg) - { - switch (errmsg) - { - case 1: - error_with_decl (newdecl, "redefinition of `%s'"); - break; - case 2: - error_with_decl (newdecl, "redeclaration of `%s'"); - break; - case 3: - error_with_decl (newdecl, "conflicting declarations of `%s'"); - break; - default: - abort (); - } - - error_with_decl (olddecl, - ((DECL_INITIAL (olddecl) - && current_binding_level == global_binding_level) - ? "`%s' previously defined here" - : "`%s' previously declared here")); - } - else if (TREE_CODE (newdecl) == TYPE_DECL - && (DECL_IN_SYSTEM_HEADER (olddecl) - || DECL_IN_SYSTEM_HEADER (newdecl))) - { - warning_with_decl (newdecl, "redefinition of `%s'"); - warning_with_decl - (olddecl, - ((DECL_INITIAL (olddecl) - && current_binding_level == global_binding_level) - ? "`%s' previously defined here" - : "`%s' previously declared here")); - } - else if (TREE_CODE (olddecl) == FUNCTION_DECL - && DECL_INITIAL (olddecl) != 0 - && TYPE_ARG_TYPES (oldtype) == 0 - && TYPE_ARG_TYPES (newtype) != 0 - && TYPE_ACTUAL_ARG_TYPES (oldtype) != 0) - { - register tree type, parm; - register int nargs; - /* Prototype decl follows defn w/o prototype. */ - - for (parm = TYPE_ACTUAL_ARG_TYPES (oldtype), - type = TYPE_ARG_TYPES (newtype), - nargs = 1; - ; - parm = TREE_CHAIN (parm), type = TREE_CHAIN (type), nargs++) - { - if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node - && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node) - { - warning_with_decl (newdecl, "prototype for `%s' follows"); - warning_with_decl (olddecl, "non-prototype definition here"); - break; - } - if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node - || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node) - { - error_with_decl (newdecl, "prototype for `%s' follows and number of arguments doesn't match"); - error_with_decl (olddecl, "non-prototype definition here"); - errmsg = 1; - break; - } - /* Type for passing arg must be consistent - with that declared for the arg. */ - if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type)) - /* If -traditional, allow `unsigned int' instead of `int' - in the prototype. */ - && (! (flag_traditional - && TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == integer_type_node - && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node))) - { - error_with_decl (newdecl, - "prototype for `%s' follows and argument %d doesn't match", - nargs); - error_with_decl (olddecl, "non-prototype definition here"); - errmsg = 1; - break; - } - } - } - /* Warn about mismatches in various flags. */ - else - { - /* Warn if function is now inline - but was previously declared not inline and has been called. */ - if (TREE_CODE (olddecl) == FUNCTION_DECL - && ! DECL_INLINE (olddecl) && DECL_INLINE (newdecl) - && TREE_USED (olddecl)) - warning_with_decl (newdecl, - "`%s' declared inline after being called"); - if (TREE_CODE (olddecl) == FUNCTION_DECL - && ! DECL_INLINE (olddecl) && DECL_INLINE (newdecl) - && DECL_INITIAL (olddecl) != 0) - warning_with_decl (newdecl, - "`%s' declared inline after its definition"); - - /* If pedantic, warn when static declaration follows a non-static - declaration. Otherwise, do so only for functions. */ - if ((pedantic || TREE_CODE (olddecl) == FUNCTION_DECL) - && TREE_PUBLIC (olddecl) - && !TREE_PUBLIC (newdecl)) - warning_with_decl (newdecl, "static declaration for `%s' follows non-static"); - - /* If warn_traditional, warn when a non-static function - declaration follows a static one. */ - if (warn_traditional - && TREE_CODE (olddecl) == FUNCTION_DECL - && !TREE_PUBLIC (olddecl) - && TREE_PUBLIC (newdecl)) - warning_with_decl (newdecl, "non-static declaration for `%s' follows static"); - - /* Warn when const declaration follows a non-const - declaration, but not for functions. */ - if (TREE_CODE (olddecl) != FUNCTION_DECL - && !TREE_READONLY (olddecl) - && TREE_READONLY (newdecl)) - warning_with_decl (newdecl, "const declaration for `%s' follows non-const"); - /* These bits are logically part of the type, for variables. - But not for functions - (where qualifiers are not valid ANSI anyway). */ - else if (pedantic && TREE_CODE (olddecl) != FUNCTION_DECL - && (TREE_READONLY (newdecl) != TREE_READONLY (olddecl) - || TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))) - pedwarn_with_decl (newdecl, "type qualifiers for `%s' conflict with previous decl"); - } - } - - /* Optionally warn about more than one declaration for the same name. */ - if (errmsg == 0 && warn_redundant_decls && DECL_SOURCE_LINE (olddecl) != 0 - /* Don't warn about a function declaration - followed by a definition. */ - && !(TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0 - && DECL_INITIAL (olddecl) == 0) - /* Don't warn about extern decl followed by (tentative) definition. */ - && !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))) - { - warning_with_decl (newdecl, "redundant redeclaration of `%s' in same scope"); - warning_with_decl (olddecl, "previous declaration of `%s'"); - } - - /* Copy all the DECL_... slots specified in the new decl - except for any that we copy here from the old type. - - Past this point, we don't change OLDTYPE and NEWTYPE - even if we change the types of NEWDECL and OLDDECL. */ - - if (types_match) - { - /* When copying info to olddecl, we store into write_olddecl - instead. This allows us to avoid modifying olddecl when - different_binding_level is true. */ - tree write_olddecl = different_binding_level ? newdecl : olddecl; - - /* Make sure we put the new type in the same obstack as the old ones. - If the old types are not both in the same obstack, use the permanent - one. */ - if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype)) - push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype)); - else - { - push_obstacks_nochange (); - end_temporary_allocation (); - } - - /* Merge the data types specified in the two decls. */ - if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl)) - { - if (different_binding_level) - TREE_TYPE (newdecl) - = build_type_attribute_variant - (newtype, - merge_attributes (TYPE_ATTRIBUTES (newtype), - TYPE_ATTRIBUTES (oldtype))); - else - TREE_TYPE (newdecl) - = TREE_TYPE (olddecl) - = common_type (newtype, oldtype); - } - - /* Lay the type out, unless already done. */ - if (oldtype != TREE_TYPE (newdecl)) - { - if (TREE_TYPE (newdecl) != error_mark_node) - layout_type (TREE_TYPE (newdecl)); - if (TREE_CODE (newdecl) != FUNCTION_DECL - && TREE_CODE (newdecl) != TYPE_DECL - && TREE_CODE (newdecl) != CONST_DECL) - layout_decl (newdecl, 0); - } - else - { - /* Since the type is OLDDECL's, make OLDDECL's size go with. */ - DECL_SIZE (newdecl) = DECL_SIZE (olddecl); - DECL_MODE (newdecl) = DECL_MODE (olddecl); - if (TREE_CODE (olddecl) != FUNCTION_DECL) - if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl)) - DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl); - } - - /* Keep the old rtl since we can safely use it. */ - DECL_RTL (newdecl) = DECL_RTL (olddecl); - - /* Merge the type qualifiers. */ - if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl) - && !TREE_THIS_VOLATILE (newdecl)) - TREE_THIS_VOLATILE (write_olddecl) = 0; - if (TREE_READONLY (newdecl)) - TREE_READONLY (write_olddecl) = 1; - if (TREE_THIS_VOLATILE (newdecl)) - { - TREE_THIS_VOLATILE (write_olddecl) = 1; - if (TREE_CODE (newdecl) == VAR_DECL) - make_var_volatile (newdecl); - } - - /* Keep source location of definition rather than declaration. */ - /* When called with different_binding_level set, keep the old - information so that meaningful diagnostics can be given. */ - if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0 - && ! different_binding_level) - { - DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl); - DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl); - } - - /* Merge the unused-warning information. */ - if (DECL_IN_SYSTEM_HEADER (olddecl)) - DECL_IN_SYSTEM_HEADER (newdecl) = 1; - else if (DECL_IN_SYSTEM_HEADER (newdecl)) - DECL_IN_SYSTEM_HEADER (write_olddecl) = 1; - - /* Merge the initialization information. */ - /* When called with different_binding_level set, don't copy over - DECL_INITIAL, so that we don't accidentally change function - declarations into function definitions. */ - if (DECL_INITIAL (newdecl) == 0 && ! different_binding_level) - DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); - - /* Merge the section attribute. - We want to issue an error if the sections conflict but that must be - done later in decl_attributes since we are called before attributes - are assigned. */ - if (DECL_SECTION_NAME (newdecl) == NULL_TREE) - DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl); - - if (TREE_CODE (newdecl) == FUNCTION_DECL) - { - DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl); - DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl); - - DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl) - |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl); - DECL_NO_CHECK_MEMORY_USAGE (newdecl) - |= DECL_NO_CHECK_MEMORY_USAGE (olddecl); - } - - pop_obstacks (); - } - /* If cannot merge, then use the new type and qualifiers, - and don't preserve the old rtl. */ - else if (! different_binding_level) - { - TREE_TYPE (olddecl) = TREE_TYPE (newdecl); - TREE_READONLY (olddecl) = TREE_READONLY (newdecl); - TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl); - TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl); - } - - /* Merge the storage class information. */ - DECL_WEAK (newdecl) |= DECL_WEAK (olddecl); - /* For functions, static overrides non-static. */ - if (TREE_CODE (newdecl) == FUNCTION_DECL) - { - TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl); - /* This is since we don't automatically - copy the attributes of NEWDECL into OLDDECL. */ - /* No need to worry about different_binding_level here because - then TREE_PUBLIC (newdecl) was true. */ - TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); - /* If this clears `static', clear it in the identifier too. */ - if (! TREE_PUBLIC (olddecl)) - TREE_PUBLIC (DECL_NAME (olddecl)) = 0; - } - if (DECL_EXTERNAL (newdecl)) - { - TREE_STATIC (newdecl) = TREE_STATIC (olddecl); - DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl); - /* An extern decl does not override previous storage class. */ - TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); - if (! DECL_EXTERNAL (newdecl)) - DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl); - } - else - { - TREE_STATIC (olddecl) = TREE_STATIC (newdecl); - TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); - } - - /* If either decl says `inline', this fn is inline, - unless its definition was passed already. */ - if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0) - DECL_INLINE (olddecl) = 1; - DECL_INLINE (newdecl) = DECL_INLINE (olddecl); - - if (TREE_CODE (newdecl) == FUNCTION_DECL) - { - if (DECL_BUILT_IN (olddecl)) - { - /* Get rid of any built-in function if new arg types don't match it - or if we have a function definition. */ - if (! types_match || new_is_definition) - { - if (! different_binding_level) - { - TREE_TYPE (olddecl) = TREE_TYPE (newdecl); - DECL_BUILT_IN (olddecl) = 0; - } - } - else - { - /* If redeclaring a builtin function, and not a definition, - it stays built in. */ - DECL_BUILT_IN (newdecl) = 1; - DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); - } - } - /* Also preserve various other info from the definition. */ - else if (! new_is_definition) - DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl); - if (! new_is_definition) - { - DECL_RESULT (newdecl) = DECL_RESULT (olddecl); - /* When called with different_binding_level set, don't copy over - DECL_INITIAL, so that we don't accidentally change function - declarations into function definitions. */ - if (! different_binding_level) - DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); - DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl); - DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl); - if (DECL_INLINE (newdecl)) - DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ORIGIN (olddecl); - } - } - if (different_binding_level) - { - /* Don't output a duplicate symbol or debugging information for this - declaration. - - Do not set TREE_ASM_WRITTEN for a FUNCTION_DECL since we may actually - just have two declarations without a definition. VAR_DECLs may need - the same treatment, I'm not sure. */ - if (TREE_CODE (newdecl) == FUNCTION_DECL) - DECL_IGNORED_P (newdecl) = 1; - else - TREE_ASM_WRITTEN (newdecl) = DECL_IGNORED_P (newdecl) = 1; - return 0; - } - - /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. - But preserve OLDDECL's DECL_UID. */ - { - register unsigned olddecl_uid = DECL_UID (olddecl); - - bcopy ((char *) newdecl + sizeof (struct tree_common), - (char *) olddecl + sizeof (struct tree_common), - sizeof (struct tree_decl) - sizeof (struct tree_common)); - DECL_UID (olddecl) = olddecl_uid; - } - - /* NEWDECL contains the merged attribute lists. - Update OLDDECL to be the same. */ - DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl); - - return 1; -} - -/* Record a decl-node X as belonging to the current lexical scope. - Check for errors (such as an incompatible declaration for the same - name already seen in the same scope). - - Returns either X or an old decl for the same name. - If an old decl is returned, it may have been smashed - to agree with what X says. */ - -tree -pushdecl (x) - tree x; -{ - register tree t; - register tree name = DECL_NAME (x); - register struct binding_level *b = current_binding_level; - - DECL_CONTEXT (x) = current_function_decl; - /* A local extern declaration for a function doesn't constitute nesting. - A local auto declaration does, since it's a forward decl - for a nested function coming later. */ - if (TREE_CODE (x) == FUNCTION_DECL && DECL_INITIAL (x) == 0 - && DECL_EXTERNAL (x)) - DECL_CONTEXT (x) = 0; - - if (warn_nested_externs && DECL_EXTERNAL (x) && b != global_binding_level - && x != IDENTIFIER_IMPLICIT_DECL (name) - /* Don't print error messages for __FUNCTION__ and __PRETTY_FUNCTION__ */ - && !DECL_IN_SYSTEM_HEADER (x)) - warning ("nested extern declaration of `%s'", IDENTIFIER_POINTER (name)); - - if (name) - { - char *file; - int line; - int different_binding_level = 0; - - t = lookup_name_current_level (name); - /* Don't type check externs here when -traditional. This is so that - code with conflicting declarations inside blocks will get warnings - not errors. X11 for instance depends on this. */ - if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional) - { - t = IDENTIFIER_GLOBAL_VALUE (name); - /* Type decls at global scope don't conflict with externs declared - inside lexical blocks. */ - if (t && TREE_CODE (t) == TYPE_DECL) - t = 0; - different_binding_level = 1; - } - if (t != 0 && t == error_mark_node) - /* error_mark_node is 0 for a while during initialization! */ - { - t = 0; - error_with_decl (x, "`%s' used prior to declaration"); - } - - if (t != 0) - { - file = DECL_SOURCE_FILE (t); - line = DECL_SOURCE_LINE (t); - } - - /* If this decl is `static' and an implicit decl was seen previously, - warn. But don't complain if -traditional, - since traditional compilers don't complain. */ - if (! flag_traditional && TREE_PUBLIC (name) - /* Don't test for DECL_EXTERNAL, because grokdeclarator - sets this for all functions. */ - && ! TREE_PUBLIC (x) - && (TREE_CODE (x) == FUNCTION_DECL || b == global_binding_level) - /* We used to warn also for explicit extern followed by static, - but sometimes you need to do it that way. */ - && IDENTIFIER_IMPLICIT_DECL (name) != 0) - { - pedwarn ("`%s' was declared implicitly `extern' and later `static'", - IDENTIFIER_POINTER (name)); - pedwarn_with_file_and_line - (DECL_SOURCE_FILE (IDENTIFIER_IMPLICIT_DECL (name)), - DECL_SOURCE_LINE (IDENTIFIER_IMPLICIT_DECL (name)), - "previous declaration of `%s'", - IDENTIFIER_POINTER (name)); - TREE_THIS_VOLATILE (name) = 1; - } - - if (t != 0 && duplicate_decls (x, t, different_binding_level)) - { - if (TREE_CODE (t) == PARM_DECL) - { - /* Don't allow more than one "real" duplicate - of a forward parm decl. */ - TREE_ASM_WRITTEN (t) = TREE_ASM_WRITTEN (x); - return t; - } - return t; - } - - /* If we are processing a typedef statement, generate a whole new - ..._TYPE node (which will be just an variant of the existing - ..._TYPE node with identical properties) and then install the - TYPE_DECL node generated to represent the typedef name as the - TYPE_NAME of this brand new (duplicate) ..._TYPE node. - - The whole point here is to end up with a situation where each - and every ..._TYPE node the compiler creates will be uniquely - associated with AT MOST one node representing a typedef name. - This way, even though the compiler substitutes corresponding - ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very - early on, later parts of the compiler can always do the reverse - translation and get back the corresponding typedef name. For - example, given: - - typedef struct S MY_TYPE; - MY_TYPE object; - - Later parts of the compiler might only know that `object' was of - type `struct S' if it were not for code just below. With this - code however, later parts of the compiler see something like: - - struct S' == struct S - typedef struct S' MY_TYPE; - struct S' object; - - And they can then deduce (from the node for type struct S') that - the original object declaration was: - - MY_TYPE object; - - Being able to do this is important for proper support of protoize, - and also for generating precise symbolic debugging information - which takes full account of the programmer's (typedef) vocabulary. - - Obviously, we don't want to generate a duplicate ..._TYPE node if - the TYPE_DECL node that we are now processing really represents a - standard built-in type. - - Since all standard types are effectively declared at line zero - in the source file, we can easily check to see if we are working - on a standard type by checking the current value of lineno. */ - - if (TREE_CODE (x) == TYPE_DECL) - { - if (DECL_SOURCE_LINE (x) == 0) - { - if (TYPE_NAME (TREE_TYPE (x)) == 0) - TYPE_NAME (TREE_TYPE (x)) = x; - } - else if (TREE_TYPE (x) != error_mark_node - && DECL_ORIGINAL_TYPE (x) == NULL_TREE) - { - tree tt = TREE_TYPE (x); - DECL_ORIGINAL_TYPE (x) = tt; - tt = build_type_copy (tt); - TYPE_NAME (tt) = x; - TREE_TYPE (x) = tt; - } - } - - /* Multiple external decls of the same identifier ought to match. - Check against both global declarations (when traditional) and out of - scope (limbo) block level declarations. - - We get warnings about inline functions where they are defined. - Avoid duplicate warnings where they are used. */ - if (TREE_PUBLIC (x) && ! DECL_INLINE (x)) - { - tree decl; - - if (flag_traditional && IDENTIFIER_GLOBAL_VALUE (name) != 0 - && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name)) - || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name)))) - decl = IDENTIFIER_GLOBAL_VALUE (name); - else if (IDENTIFIER_LIMBO_VALUE (name) != 0) - /* Decls in limbo are always extern, so no need to check that. */ - decl = IDENTIFIER_LIMBO_VALUE (name); - else - decl = 0; - - if (decl && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl)) - /* If old decl is built-in, we already warned if we should. */ - && !DECL_BUILT_IN (decl)) - { - pedwarn_with_decl (x, - "type mismatch with previous external decl"); - pedwarn_with_decl (decl, "previous external decl of `%s'"); - } - } - - /* If a function has had an implicit declaration, and then is defined, - make sure they are compatible. */ - - if (IDENTIFIER_IMPLICIT_DECL (name) != 0 - && IDENTIFIER_GLOBAL_VALUE (name) == 0 - && TREE_CODE (x) == FUNCTION_DECL - && ! comptypes (TREE_TYPE (x), - TREE_TYPE (IDENTIFIER_IMPLICIT_DECL (name)))) - { - warning_with_decl (x, "type mismatch with previous implicit declaration"); - warning_with_decl (IDENTIFIER_IMPLICIT_DECL (name), - "previous implicit declaration of `%s'"); - } - - /* In PCC-compatibility mode, extern decls of vars with no current decl - take effect at top level no matter where they are. */ - if (flag_traditional && DECL_EXTERNAL (x) - && lookup_name (name) == 0) - { - tree type = TREE_TYPE (x); - - /* But don't do this if the type contains temporary nodes. */ - while (type) - { - if (type == error_mark_node) - break; - if (! TREE_PERMANENT (type)) - { - warning_with_decl (x, "type of external `%s' is not global"); - /* By exiting the loop early, we leave TYPE nonzero, - and thus prevent globalization of the decl. */ - break; - } - else if (TREE_CODE (type) == FUNCTION_TYPE - && TYPE_ARG_TYPES (type) != 0) - /* The types might not be truly local, - but the list of arg types certainly is temporary. - Since prototypes are nontraditional, - ok not to do the traditional thing. */ - break; - type = TREE_TYPE (type); - } - - if (type == 0) - b = global_binding_level; - } - - /* This name is new in its binding level. - Install the new declaration and return it. */ - if (b == global_binding_level) - { - /* Install a global value. */ - - /* If the first global decl has external linkage, - warn if we later see static one. */ - if (IDENTIFIER_GLOBAL_VALUE (name) == 0 && TREE_PUBLIC (x)) - TREE_PUBLIC (name) = 1; - - IDENTIFIER_GLOBAL_VALUE (name) = x; - - /* We no longer care about any previous block level declarations. */ - IDENTIFIER_LIMBO_VALUE (name) = 0; - - /* Don't forget if the function was used via an implicit decl. */ - if (IDENTIFIER_IMPLICIT_DECL (name) - && TREE_USED (IDENTIFIER_IMPLICIT_DECL (name))) - TREE_USED (x) = 1, TREE_USED (name) = 1; - - /* Don't forget if its address was taken in that way. */ - if (IDENTIFIER_IMPLICIT_DECL (name) - && TREE_ADDRESSABLE (IDENTIFIER_IMPLICIT_DECL (name))) - TREE_ADDRESSABLE (x) = 1; - - /* Warn about mismatches against previous implicit decl. */ - if (IDENTIFIER_IMPLICIT_DECL (name) != 0 - /* If this real decl matches the implicit, don't complain. */ - && ! (TREE_CODE (x) == FUNCTION_DECL - && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (x))) - == integer_type_node))) - pedwarn ("`%s' was previously implicitly declared to return `int'", - IDENTIFIER_POINTER (name)); - - /* If this decl is `static' and an `extern' was seen previously, - that is erroneous. */ - if (TREE_PUBLIC (name) - && ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x)) - { - /* Okay to redeclare an ANSI built-in as static. */ - if (t != 0 && DECL_BUILT_IN (t)) - ; - /* Okay to declare a non-ANSI built-in as anything. */ - else if (t != 0 && DECL_BUILT_IN_NONANSI (t)) - ; - /* Okay to have global type decl after an earlier extern - declaration inside a lexical block. */ - else if (TREE_CODE (x) == TYPE_DECL) - ; - else if (IDENTIFIER_IMPLICIT_DECL (name)) - { - if (! TREE_THIS_VOLATILE (name)) - pedwarn ("`%s' was declared implicitly `extern' and later `static'", - IDENTIFIER_POINTER (name)); - } - else - pedwarn ("`%s' was declared `extern' and later `static'", - IDENTIFIER_POINTER (name)); - } - } - else - { - /* Here to install a non-global value. */ - tree oldlocal = IDENTIFIER_LOCAL_VALUE (name); - tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name); - IDENTIFIER_LOCAL_VALUE (name) = x; - - /* If this is an extern function declaration, see if we - have a global definition or declaration for the function. */ - if (oldlocal == 0 - && DECL_EXTERNAL (x) && !DECL_INLINE (x) - && oldglobal != 0 - && TREE_CODE (x) == FUNCTION_DECL - && TREE_CODE (oldglobal) == FUNCTION_DECL) - { - /* We have one. Their types must agree. */ - if (! comptypes (TREE_TYPE (x), - TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name)))) - pedwarn_with_decl (x, "extern declaration of `%s' doesn't match global one"); - else - { - /* Inner extern decl is inline if global one is. - Copy enough to really inline it. */ - if (DECL_INLINE (oldglobal)) - { - DECL_INLINE (x) = DECL_INLINE (oldglobal); - DECL_INITIAL (x) = (current_function_decl == oldglobal - ? 0 : DECL_INITIAL (oldglobal)); - DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal); - DECL_FRAME_SIZE (x) = DECL_FRAME_SIZE (oldglobal); - DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal); - DECL_RESULT (x) = DECL_RESULT (oldglobal); - TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal); - DECL_ABSTRACT_ORIGIN (x) = DECL_ORIGIN (oldglobal); - } - /* Inner extern decl is built-in if global one is. */ - if (DECL_BUILT_IN (oldglobal)) - { - DECL_BUILT_IN (x) = DECL_BUILT_IN (oldglobal); - DECL_FUNCTION_CODE (x) = DECL_FUNCTION_CODE (oldglobal); - } - /* Keep the arg types from a file-scope fcn defn. */ - if (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != 0 - && DECL_INITIAL (oldglobal) - && TYPE_ARG_TYPES (TREE_TYPE (x)) == 0) - TREE_TYPE (x) = TREE_TYPE (oldglobal); - } - } - -#if 0 /* This case is probably sometimes the right thing to do. */ - /* If we have a local external declaration, - then any file-scope declaration should not - have been static. */ - if (oldlocal == 0 && oldglobal != 0 - && !TREE_PUBLIC (oldglobal) - && DECL_EXTERNAL (x) && TREE_PUBLIC (x)) - warning ("`%s' locally external but globally static", - IDENTIFIER_POINTER (name)); -#endif - - /* If we have a local external declaration, - and no file-scope declaration has yet been seen, - then if we later have a file-scope decl it must not be static. */ - if (oldlocal == 0 - && DECL_EXTERNAL (x) - && TREE_PUBLIC (x)) - { - if (oldglobal == 0) - TREE_PUBLIC (name) = 1; - - /* Save this decl, so that we can do type checking against - other decls after it falls out of scope. - - Only save it once. This prevents temporary decls created in - expand_inline_function from being used here, since this - will have been set when the inline function was parsed. - It also helps give slightly better warnings. */ - if (IDENTIFIER_LIMBO_VALUE (name) == 0) - IDENTIFIER_LIMBO_VALUE (name) = x; - } - - /* Warn if shadowing an argument at the top level of the body. */ - if (oldlocal != 0 && !DECL_EXTERNAL (x) - /* This warning doesn't apply to the parms of a nested fcn. */ - && ! current_binding_level->parm_flag - /* Check that this is one level down from the parms. */ - && current_binding_level->level_chain->parm_flag - /* Check that the decl being shadowed - comes from the parm level, one level up. */ - && chain_member (oldlocal, current_binding_level->level_chain->names)) - { - if (TREE_CODE (oldlocal) == PARM_DECL) - pedwarn ("declaration of `%s' shadows a parameter", - IDENTIFIER_POINTER (name)); - else - pedwarn ("declaration of `%s' shadows a symbol from the parameter list", - IDENTIFIER_POINTER (name)); - } - - /* Maybe warn if shadowing something else. */ - else if (warn_shadow && !DECL_EXTERNAL (x) - /* No shadow warnings for internally generated vars. */ - && DECL_SOURCE_LINE (x) != 0 - /* No shadow warnings for vars made for inlining. */ - && ! DECL_FROM_INLINE (x)) - { - char *id = IDENTIFIER_POINTER (name); - - if (TREE_CODE (x) == PARM_DECL - && current_binding_level->level_chain->parm_flag) - /* Don't warn about the parm names in function declarator - within a function declarator. - It would be nice to avoid warning in any function - declarator in a declaration, as opposed to a definition, - but there is no way to tell it's not a definition. */ - ; - else if (oldlocal != 0 && TREE_CODE (oldlocal) == PARM_DECL) - warning ("declaration of `%s' shadows a parameter", id); - else if (oldlocal != 0) - warning ("declaration of `%s' shadows previous local", id); - else if (IDENTIFIER_GLOBAL_VALUE (name) != 0 - && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node) - warning ("declaration of `%s' shadows global declaration", id); - } - - /* If storing a local value, there may already be one (inherited). - If so, record it for restoration when this binding level ends. */ - if (oldlocal != 0) - b->shadowed = tree_cons (name, oldlocal, b->shadowed); - } - - /* Keep count of variables in this level with incomplete type. */ - if (TYPE_SIZE (TREE_TYPE (x)) == 0) - ++b->n_incomplete; - } - - /* Put decls on list in reverse order. - We will reverse them later if necessary. */ - TREE_CHAIN (x) = b->names; - b->names = x; - - return x; -} - -/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */ - -tree -pushdecl_top_level (x) - tree x; -{ - register tree t; - register struct binding_level *b = current_binding_level; - - current_binding_level = global_binding_level; - t = pushdecl (x); - current_binding_level = b; - return t; -} - -/* Generate an implicit declaration for identifier FUNCTIONID - as a function of type int (). Print a warning if appropriate. */ - -tree -implicitly_declare (functionid) - tree functionid; -{ - register tree decl; - int traditional_warning = 0; - /* Only one "implicit declaration" warning per identifier. */ - int implicit_warning; - - /* Save the decl permanently so we can warn if definition follows. */ - push_obstacks_nochange (); - end_temporary_allocation (); - - /* We used to reuse an old implicit decl here, - but this loses with inline functions because it can clobber - the saved decl chains. */ -/* if (IDENTIFIER_IMPLICIT_DECL (functionid) != 0) - decl = IDENTIFIER_IMPLICIT_DECL (functionid); - else */ - decl = build_decl (FUNCTION_DECL, functionid, default_function_type); - - /* Warn of implicit decl following explicit local extern decl. - This is probably a program designed for traditional C. */ - if (TREE_PUBLIC (functionid) && IDENTIFIER_GLOBAL_VALUE (functionid) == 0) - traditional_warning = 1; - - /* Warn once of an implicit declaration. */ - implicit_warning = (IDENTIFIER_IMPLICIT_DECL (functionid) == 0); - - DECL_EXTERNAL (decl) = 1; - TREE_PUBLIC (decl) = 1; - - /* Record that we have an implicit decl and this is it. */ - IDENTIFIER_IMPLICIT_DECL (functionid) = decl; - - /* ANSI standard says implicit declarations are in the innermost block. - So we record the decl in the standard fashion. - If flag_traditional is set, pushdecl does it top-level. */ - pushdecl (decl); - - /* This is a no-op in c-lang.c or something real in objc-actions.c. */ - maybe_objc_check_decl (decl); - - rest_of_decl_compilation (decl, NULL_PTR, 0, 0); - - if (mesg_implicit_function_declaration && implicit_warning) - { - if (mesg_implicit_function_declaration == 2) - error ("implicit declaration of function `%s'", - IDENTIFIER_POINTER (functionid)); - else - warning ("implicit declaration of function `%s'", - IDENTIFIER_POINTER (functionid)); - } - else if (warn_traditional && traditional_warning) - warning ("function `%s' was previously declared within a block", - IDENTIFIER_POINTER (functionid)); - - /* Write a record describing this implicit function declaration to the - prototypes file (if requested). */ - - gen_aux_info_record (decl, 0, 1, 0); - - pop_obstacks (); - - return decl; -} - -/* Return zero if the declaration NEWDECL is valid - when the declaration OLDDECL (assumed to be for the same name) - has already been seen. - Otherwise return 1 if NEWDECL is a redefinition, 2 if it is a redeclaration, - and 3 if it is a conflicting declaration. */ - -static int -redeclaration_error_message (newdecl, olddecl) - tree newdecl, olddecl; -{ - if (TREE_CODE (newdecl) == TYPE_DECL) - { - if (flag_traditional && TREE_TYPE (newdecl) == TREE_TYPE (olddecl)) - return 0; - /* pushdecl creates distinct types for TYPE_DECLs by calling - build_type_copy, so the above comparison generally fails. We do - another test against the TYPE_MAIN_VARIANT of the olddecl, which - is equivalent to what this code used to do before the build_type_copy - call. The variant type distinction should not matter for traditional - code, because it doesn't have type qualifiers. */ - if (flag_traditional - && TYPE_MAIN_VARIANT (TREE_TYPE (olddecl)) == TREE_TYPE (newdecl)) - return 0; - if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl)) - return 0; - return 1; - } - else if (TREE_CODE (newdecl) == FUNCTION_DECL) - { - /* Declarations of functions can insist on internal linkage - but they can't be inconsistent with internal linkage, - so there can be no error on that account. - However defining the same name twice is no good. */ - if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0 - /* However, defining once as extern inline and a second - time in another way is ok. */ - && !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl) - && !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl)))) - return 1; - return 0; - } - else if (current_binding_level == global_binding_level) - { - /* Objects declared at top level: */ - /* If at least one is a reference, it's ok. */ - if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl)) - return 0; - /* Reject two definitions. */ - if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0) - return 1; - /* Now we have two tentative defs, or one tentative and one real def. */ - /* Insist that the linkage match. */ - if (TREE_PUBLIC (olddecl) != TREE_PUBLIC (newdecl)) - return 3; - return 0; - } - else if (current_binding_level->parm_flag - && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl)) - return 0; - else - { - /* Newdecl has block scope. If olddecl has block scope also, then - reject two definitions, and reject a definition together with an - external reference. Otherwise, it is OK, because newdecl must - be an extern reference to olddecl. */ - if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)) - && DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl)) - return 2; - return 0; - } -} - -/* Get the LABEL_DECL corresponding to identifier ID as a label. - Create one if none exists so far for the current function. - This function is called for both label definitions and label references. */ - -tree -lookup_label (id) - tree id; -{ - register tree decl = IDENTIFIER_LABEL_VALUE (id); - - if (current_function_decl == 0) - { - error ("label %s referenced outside of any function", - IDENTIFIER_POINTER (id)); - return 0; - } - - /* Use a label already defined or ref'd with this name. */ - if (decl != 0) - { - /* But not if it is inherited and wasn't declared to be inheritable. */ - if (DECL_CONTEXT (decl) != current_function_decl - && ! C_DECLARED_LABEL_FLAG (decl)) - return shadow_label (id); - return decl; - } - - decl = build_decl (LABEL_DECL, id, void_type_node); - - /* Make sure every label has an rtx. */ - label_rtx (decl); - - /* A label not explicitly declared must be local to where it's ref'd. */ - DECL_CONTEXT (decl) = current_function_decl; - - DECL_MODE (decl) = VOIDmode; - - /* Say where one reference is to the label, - for the sake of the error if it is not defined. */ - DECL_SOURCE_LINE (decl) = lineno; - DECL_SOURCE_FILE (decl) = input_filename; - - IDENTIFIER_LABEL_VALUE (id) = decl; - - named_labels = tree_cons (NULL_TREE, decl, named_labels); - - return decl; -} - -/* Make a label named NAME in the current function, - shadowing silently any that may be inherited from containing functions - or containing scopes. - - Note that valid use, if the label being shadowed - comes from another scope in the same function, - requires calling declare_nonlocal_label right away. */ - -tree -shadow_label (name) - tree name; -{ - register tree decl = IDENTIFIER_LABEL_VALUE (name); - - if (decl != 0) - { - register tree dup; - - /* Check to make sure that the label hasn't already been declared - at this label scope */ - for (dup = named_labels; dup; dup = TREE_CHAIN (dup)) - if (TREE_VALUE (dup) == decl) - { - error ("duplicate label declaration `%s'", - IDENTIFIER_POINTER (name)); - error_with_decl (TREE_VALUE (dup), - "this is a previous declaration"); - /* Just use the previous declaration. */ - return lookup_label (name); - } - - shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels); - IDENTIFIER_LABEL_VALUE (name) = decl = 0; - } - - return lookup_label (name); -} - -/* Define a label, specifying the location in the source file. - Return the LABEL_DECL node for the label, if the definition is valid. - Otherwise return 0. */ - -tree -define_label (filename, line, name) - char *filename; - int line; - tree name; -{ - tree decl = lookup_label (name); - - /* If label with this name is known from an outer context, shadow it. */ - if (decl != 0 && DECL_CONTEXT (decl) != current_function_decl) - { - shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels); - IDENTIFIER_LABEL_VALUE (name) = 0; - decl = lookup_label (name); - } - - if (DECL_INITIAL (decl) != 0) - { - error ("duplicate label `%s'", IDENTIFIER_POINTER (name)); - return 0; - } - else - { - /* Mark label as having been defined. */ - DECL_INITIAL (decl) = error_mark_node; - /* Say where in the source. */ - DECL_SOURCE_FILE (decl) = filename; - DECL_SOURCE_LINE (decl) = line; - return decl; - } -} - -/* Return the list of declarations of the current level. - Note that this list is in reverse order unless/until - you nreverse it; and when you do nreverse it, you must - store the result back using `storedecls' or you will lose. */ - -tree -getdecls () -{ - return current_binding_level->names; -} - -/* Return the list of type-tags (for structs, etc) of the current level. */ - -tree -gettags () -{ - return current_binding_level->tags; -} - -/* Store the list of declarations of the current level. - This is done for the parameter declarations of a function being defined, - after they are modified in the light of any missing parameters. */ - -static void -storedecls (decls) - tree decls; -{ - current_binding_level->names = decls; -} - -/* Similarly, store the list of tags of the current level. */ - -static void -storetags (tags) - tree tags; -{ - current_binding_level->tags = tags; -} - -/* Given NAME, an IDENTIFIER_NODE, - return the structure (or union or enum) definition for that name. - Searches binding levels from BINDING_LEVEL up to the global level. - If THISLEVEL_ONLY is nonzero, searches only the specified context - (but skips any tag-transparent contexts to find one that is - meaningful for tags). - CODE says which kind of type the caller wants; - it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE. - If the wrong kind of type is found, an error is reported. */ - -static tree -lookup_tag (code, name, binding_level, thislevel_only) - enum tree_code code; - struct binding_level *binding_level; - tree name; - int thislevel_only; -{ - register struct binding_level *level; - - for (level = binding_level; level; level = level->level_chain) - { - register tree tail; - for (tail = level->tags; tail; tail = TREE_CHAIN (tail)) - { - if (TREE_PURPOSE (tail) == name) - { - if (TREE_CODE (TREE_VALUE (tail)) != code) - { - /* Definition isn't the kind we were looking for. */ - pending_invalid_xref = name; - pending_invalid_xref_file = input_filename; - pending_invalid_xref_line = lineno; - } - return TREE_VALUE (tail); - } - } - if (thislevel_only && ! level->tag_transparent) - return NULL_TREE; - } - return NULL_TREE; -} - -/* Print an error message now - for a recent invalid struct, union or enum cross reference. - We don't print them immediately because they are not invalid - when used in the `struct foo;' construct for shadowing. */ - -void -pending_xref_error () -{ - if (pending_invalid_xref != 0) - error_with_file_and_line (pending_invalid_xref_file, - pending_invalid_xref_line, - "`%s' defined as wrong kind of tag", - IDENTIFIER_POINTER (pending_invalid_xref)); - pending_invalid_xref = 0; -} - -/* Given a type, find the tag that was defined for it and return the tag name. - Otherwise return 0. */ - -static tree -lookup_tag_reverse (type) - tree type; -{ - register struct binding_level *level; - - for (level = current_binding_level; level; level = level->level_chain) - { - register tree tail; - for (tail = level->tags; tail; tail = TREE_CHAIN (tail)) - { - if (TREE_VALUE (tail) == type) - return TREE_PURPOSE (tail); - } - } - return NULL_TREE; -} - -/* Look up NAME in the current binding level and its superiors - in the namespace of variables, functions and typedefs. - Return a ..._DECL node of some kind representing its definition, - or return 0 if it is undefined. */ - -tree -lookup_name (name) - tree name; -{ - register tree val; - if (current_binding_level != global_binding_level - && IDENTIFIER_LOCAL_VALUE (name)) - val = IDENTIFIER_LOCAL_VALUE (name); - else - val = IDENTIFIER_GLOBAL_VALUE (name); - return val; -} - -/* Similar to `lookup_name' but look only at current binding level. */ - -tree -lookup_name_current_level (name) - tree name; -{ - register tree t; - - if (current_binding_level == global_binding_level) - return IDENTIFIER_GLOBAL_VALUE (name); - - if (IDENTIFIER_LOCAL_VALUE (name) == 0) - return 0; - - for (t = current_binding_level->names; t; t = TREE_CHAIN (t)) - if (DECL_NAME (t) == name) - break; - - return t; -} - -/* Create the predefined scalar types of C, - and some nodes representing standard constants (0, 1, (void *) 0). - Initialize the global binding level. - Make definitions for built-in primitive functions. */ - -void -init_decl_processing () -{ - register tree endlink; - /* Either char* or void*. */ - tree traditional_ptr_type_node; - /* Data types of memcpy and strlen. */ - tree memcpy_ftype, memset_ftype, strlen_ftype; - tree void_ftype_any, ptr_ftype_void, ptr_ftype_ptr; - int wchar_type_size; - tree temp; - tree array_domain_type; - - current_function_decl = NULL; - named_labels = NULL; - current_binding_level = NULL_BINDING_LEVEL; - free_binding_level = NULL_BINDING_LEVEL; - pushlevel (0); /* make the binding_level structure for global names */ - global_binding_level = current_binding_level; - - /* Define `int' and `char' first so that dbx will output them first. */ - - integer_type_node = make_signed_type (INT_TYPE_SIZE); - pushdecl (build_decl (TYPE_DECL, ridpointers[(int) RID_INT], - integer_type_node)); - - /* Define `char', which is like either `signed char' or `unsigned char' - but not the same as either. */ - - char_type_node - = (flag_signed_char - ? make_signed_type (CHAR_TYPE_SIZE) - : make_unsigned_type (CHAR_TYPE_SIZE)); - pushdecl (build_decl (TYPE_DECL, get_identifier ("char"), - char_type_node)); - - long_integer_type_node = make_signed_type (LONG_TYPE_SIZE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"), - long_integer_type_node)); - - unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"), - unsigned_type_node)); - - long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"), - long_unsigned_type_node)); - - long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"), - long_long_integer_type_node)); - - long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"), - long_long_unsigned_type_node)); - - short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"), - short_integer_type_node)); - - short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"), - short_unsigned_type_node)); - - /* `unsigned long' is the standard type for sizeof. - Traditionally, use a signed type. - Note that stddef.h uses `unsigned long', - and this must agree, even if long and int are the same size. */ - set_sizetype - (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)))); - if (flag_traditional && TREE_UNSIGNED (sizetype)) - set_sizetype (signed_type (sizetype)); - - ptrdiff_type_node - = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE))); - - error_mark_node = make_node (ERROR_MARK); - TREE_TYPE (error_mark_node) = error_mark_node; - - /* Define both `signed char' and `unsigned char'. */ - signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"), - signed_char_type_node)); - - unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"), - unsigned_char_type_node)); - - intQI_type_node = make_signed_type (GET_MODE_BITSIZE (QImode)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node)); - - intHI_type_node = make_signed_type (GET_MODE_BITSIZE (HImode)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, intHI_type_node)); - - intSI_type_node = make_signed_type (GET_MODE_BITSIZE (SImode)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node)); - - intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node)); - -#if HOST_BITS_PER_WIDE_INT >= 64 - intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node)); -#endif - - unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node)); - - unsigned_intHI_type_node = make_unsigned_type (GET_MODE_BITSIZE (HImode)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intHI_type_node)); - - unsigned_intSI_type_node = make_unsigned_type (GET_MODE_BITSIZE (SImode)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node)); - - unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node)); - -#if HOST_BITS_PER_WIDE_INT >= 64 - unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode)); - pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node)); -#endif - - float_type_node = make_node (REAL_TYPE); - TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE; - pushdecl (build_decl (TYPE_DECL, ridpointers[(int) RID_FLOAT], - float_type_node)); - layout_type (float_type_node); - - double_type_node = make_node (REAL_TYPE); - if (flag_short_double) - TYPE_PRECISION (double_type_node) = FLOAT_TYPE_SIZE; - else - TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE; - pushdecl (build_decl (TYPE_DECL, ridpointers[(int) RID_DOUBLE], - double_type_node)); - layout_type (double_type_node); - - long_double_type_node = make_node (REAL_TYPE); - TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE; - pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"), - long_double_type_node)); - layout_type (long_double_type_node); - - complex_integer_type_node = make_node (COMPLEX_TYPE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"), - complex_integer_type_node)); - TREE_TYPE (complex_integer_type_node) = integer_type_node; - layout_type (complex_integer_type_node); - - complex_float_type_node = make_node (COMPLEX_TYPE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"), - complex_float_type_node)); - TREE_TYPE (complex_float_type_node) = float_type_node; - layout_type (complex_float_type_node); - - complex_double_type_node = make_node (COMPLEX_TYPE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"), - complex_double_type_node)); - TREE_TYPE (complex_double_type_node) = double_type_node; - layout_type (complex_double_type_node); - - complex_long_double_type_node = make_node (COMPLEX_TYPE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"), - complex_long_double_type_node)); - TREE_TYPE (complex_long_double_type_node) = long_double_type_node; - layout_type (complex_long_double_type_node); - - wchar_type_node - = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WCHAR_TYPE))); - wchar_type_size = TYPE_PRECISION (wchar_type_node); - signed_wchar_type_node = signed_type (wchar_type_node); - unsigned_wchar_type_node = unsigned_type (wchar_type_node); - - integer_zero_node = build_int_2 (0, 0); - TREE_TYPE (integer_zero_node) = integer_type_node; - integer_one_node = build_int_2 (1, 0); - TREE_TYPE (integer_one_node) = integer_type_node; - - boolean_type_node = integer_type_node; - boolean_true_node = integer_one_node; - boolean_false_node = integer_zero_node; - - size_zero_node = build_int_2 (0, 0); - TREE_TYPE (size_zero_node) = sizetype; - size_one_node = build_int_2 (1, 0); - TREE_TYPE (size_one_node) = sizetype; - - void_type_node = make_node (VOID_TYPE); - pushdecl (build_decl (TYPE_DECL, - ridpointers[(int) RID_VOID], void_type_node)); - layout_type (void_type_node); /* Uses integer_zero_node */ - /* We are not going to have real types in C with less than byte alignment, - so we might as well not have any types that claim to have it. */ - TYPE_ALIGN (void_type_node) = BITS_PER_UNIT; - - null_pointer_node = build_int_2 (0, 0); - TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node); - layout_type (TREE_TYPE (null_pointer_node)); - - string_type_node = build_pointer_type (char_type_node); - const_string_type_node - = build_pointer_type (build_type_variant (char_type_node, 1, 0)); - - /* Make a type to be the domain of a few array types - whose domains don't really matter. - 200 is small enough that it always fits in size_t - and large enough that it can hold most function names for the - initializations of __FUNCTION__ and __PRETTY_FUNCTION__. */ - array_domain_type = build_index_type (build_int_2 (200, 0)); - - /* make a type for arrays of characters. - With luck nothing will ever really depend on the length of this - array type. */ - char_array_type_node - = build_array_type (char_type_node, array_domain_type); - /* Likewise for arrays of ints. */ - int_array_type_node - = build_array_type (integer_type_node, array_domain_type); - /* This is for wide string constants. */ - wchar_array_type_node - = build_array_type (wchar_type_node, array_domain_type); - - default_function_type - = build_function_type (integer_type_node, NULL_TREE); - - ptr_type_node = build_pointer_type (void_type_node); - const_ptr_type_node - = build_pointer_type (build_type_variant (void_type_node, 1, 0)); - - endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE); - - void_ftype_any - = build_function_type (void_type_node, NULL_TREE); - - float_ftype_float - = build_function_type (float_type_node, - tree_cons (NULL_TREE, float_type_node, endlink)); - - double_ftype_double - = build_function_type (double_type_node, - tree_cons (NULL_TREE, double_type_node, endlink)); - - ldouble_ftype_ldouble - = build_function_type (long_double_type_node, - tree_cons (NULL_TREE, long_double_type_node, - endlink)); - - double_ftype_double_double - = build_function_type (double_type_node, - tree_cons (NULL_TREE, double_type_node, - tree_cons (NULL_TREE, - double_type_node, endlink))); - - int_ftype_int - = build_function_type (integer_type_node, - tree_cons (NULL_TREE, integer_type_node, endlink)); - - long_ftype_long - = build_function_type (long_integer_type_node, - tree_cons (NULL_TREE, - long_integer_type_node, endlink)); - - void_ftype_ptr_ptr_int - = build_function_type (void_type_node, - tree_cons (NULL_TREE, ptr_type_node, - tree_cons (NULL_TREE, ptr_type_node, - tree_cons (NULL_TREE, - integer_type_node, - endlink)))); - - int_ftype_cptr_cptr_sizet - = build_function_type (integer_type_node, - tree_cons (NULL_TREE, const_ptr_type_node, - tree_cons (NULL_TREE, const_ptr_type_node, - tree_cons (NULL_TREE, - sizetype, - endlink)))); - - void_ftype_ptr_int_int - = build_function_type (void_type_node, - tree_cons (NULL_TREE, ptr_type_node, - tree_cons (NULL_TREE, integer_type_node, - tree_cons (NULL_TREE, - integer_type_node, - endlink)))); - - string_ftype_ptr_ptr /* strcpy prototype */ - = build_function_type (string_type_node, - tree_cons (NULL_TREE, string_type_node, - tree_cons (NULL_TREE, - const_string_type_node, - endlink))); - - int_ftype_string_string /* strcmp prototype */ - = build_function_type (integer_type_node, - tree_cons (NULL_TREE, const_string_type_node, - tree_cons (NULL_TREE, - const_string_type_node, - endlink))); - - strlen_ftype /* strlen prototype */ - = build_function_type (flag_traditional ? integer_type_node : sizetype, - tree_cons (NULL_TREE, const_string_type_node, - endlink)); - - traditional_ptr_type_node - = (flag_traditional ? string_type_node : ptr_type_node); - - memcpy_ftype /* memcpy prototype */ - = build_function_type (traditional_ptr_type_node, - tree_cons (NULL_TREE, ptr_type_node, - tree_cons (NULL_TREE, const_ptr_type_node, - tree_cons (NULL_TREE, - sizetype, - endlink)))); - - memset_ftype /* memset prototype */ - = build_function_type (traditional_ptr_type_node, - tree_cons (NULL_TREE, ptr_type_node, - tree_cons (NULL_TREE, integer_type_node, - tree_cons (NULL_TREE, - sizetype, - endlink)))); - - ptr_ftype_void = build_function_type (ptr_type_node, endlink); - ptr_ftype_ptr - = build_function_type (ptr_type_node, - tree_cons (NULL_TREE, ptr_type_node, endlink)); - - builtin_function ("__builtin_constant_p", default_function_type, - BUILT_IN_CONSTANT_P, NULL_PTR); - - builtin_function ("__builtin_return_address", - build_function_type (ptr_type_node, - tree_cons (NULL_TREE, - unsigned_type_node, - endlink)), - BUILT_IN_RETURN_ADDRESS, NULL_PTR); - - builtin_function ("__builtin_frame_address", - build_function_type (ptr_type_node, - tree_cons (NULL_TREE, - unsigned_type_node, - endlink)), - BUILT_IN_FRAME_ADDRESS, NULL_PTR); - - builtin_function ("__builtin_aggregate_incoming_address", - build_function_type (ptr_type_node, NULL_TREE), - BUILT_IN_AGGREGATE_INCOMING_ADDRESS, NULL_PTR); - - /* Hooks for the DWARF 2 __throw routine. */ - builtin_function ("__builtin_unwind_init", - build_function_type (void_type_node, endlink), - BUILT_IN_UNWIND_INIT, NULL_PTR); - builtin_function ("__builtin_dwarf_cfa", ptr_ftype_void, - BUILT_IN_DWARF_CFA, NULL_PTR); - builtin_function ("__builtin_dwarf_fp_regnum", - build_function_type (unsigned_type_node, endlink), - BUILT_IN_DWARF_FP_REGNUM, NULL_PTR); - builtin_function ("__builtin_dwarf_reg_size", int_ftype_int, - BUILT_IN_DWARF_REG_SIZE, NULL_PTR); - builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr, - BUILT_IN_FROB_RETURN_ADDR, NULL_PTR); - builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr, - BUILT_IN_EXTRACT_RETURN_ADDR, NULL_PTR); - builtin_function - ("__builtin_eh_return", - build_function_type (void_type_node, - tree_cons (NULL_TREE, ptr_type_node, - tree_cons (NULL_TREE, - type_for_mode (ptr_mode, 0), - tree_cons (NULL_TREE, - ptr_type_node, - endlink)))), - BUILT_IN_EH_RETURN, NULL_PTR); - - builtin_function ("__builtin_alloca", - build_function_type (ptr_type_node, - tree_cons (NULL_TREE, - sizetype, - endlink)), - BUILT_IN_ALLOCA, "alloca"); - builtin_function ("__builtin_ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR); - /* Define alloca, ffs as builtins. - Declare _exit just to mark it as volatile. */ - if (! flag_no_builtin && !flag_no_nonansi_builtin) - { - temp = builtin_function ("alloca", - build_function_type (ptr_type_node, - tree_cons (NULL_TREE, - sizetype, - endlink)), - BUILT_IN_ALLOCA, NULL_PTR); - /* Suppress error if redefined as a non-function. */ - DECL_BUILT_IN_NONANSI (temp) = 1; - temp = builtin_function ("ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR); - /* Suppress error if redefined as a non-function. */ - DECL_BUILT_IN_NONANSI (temp) = 1; - temp = builtin_function ("_exit", void_ftype_any, NOT_BUILT_IN, - NULL_PTR); - TREE_THIS_VOLATILE (temp) = 1; - TREE_SIDE_EFFECTS (temp) = 1; - /* Suppress error if redefined as a non-function. */ - DECL_BUILT_IN_NONANSI (temp) = 1; - } - - builtin_function ("__builtin_abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR); - builtin_function ("__builtin_fabsf", float_ftype_float, BUILT_IN_FABS, - NULL_PTR); - builtin_function ("__builtin_fabs", double_ftype_double, BUILT_IN_FABS, - NULL_PTR); - builtin_function ("__builtin_fabsl", ldouble_ftype_ldouble, BUILT_IN_FABS, - NULL_PTR); - builtin_function ("__builtin_labs", long_ftype_long, BUILT_IN_LABS, - NULL_PTR); - builtin_function ("__builtin_saveregs", - build_function_type (ptr_type_node, NULL_TREE), - BUILT_IN_SAVEREGS, NULL_PTR); -/* EXPAND_BUILTIN_VARARGS is obsolete. */ -#if 0 - builtin_function ("__builtin_varargs", - build_function_type (ptr_type_node, - tree_cons (NULL_TREE, - integer_type_node, - endlink)), - BUILT_IN_VARARGS, NULL_PTR); -#endif - builtin_function ("__builtin_classify_type", default_function_type, - BUILT_IN_CLASSIFY_TYPE, NULL_PTR); - builtin_function ("__builtin_next_arg", - build_function_type (ptr_type_node, NULL_TREE), - BUILT_IN_NEXT_ARG, NULL_PTR); - builtin_function ("__builtin_args_info", - build_function_type (integer_type_node, - tree_cons (NULL_TREE, - integer_type_node, - endlink)), - BUILT_IN_ARGS_INFO, NULL_PTR); - - /* Untyped call and return. */ - builtin_function ("__builtin_apply_args", - build_function_type (ptr_type_node, NULL_TREE), - BUILT_IN_APPLY_ARGS, NULL_PTR); - - temp = tree_cons (NULL_TREE, - build_pointer_type (build_function_type (void_type_node, - NULL_TREE)), - tree_cons (NULL_TREE, - ptr_type_node, - tree_cons (NULL_TREE, - sizetype, - endlink))); - builtin_function ("__builtin_apply", - build_function_type (ptr_type_node, temp), - BUILT_IN_APPLY, NULL_PTR); - builtin_function ("__builtin_return", - build_function_type (void_type_node, - tree_cons (NULL_TREE, - ptr_type_node, - endlink)), - BUILT_IN_RETURN, NULL_PTR); - - /* Currently under experimentation. */ - builtin_function ("__builtin_memcpy", memcpy_ftype, - BUILT_IN_MEMCPY, "memcpy"); - builtin_function ("__builtin_memcmp", int_ftype_cptr_cptr_sizet, - BUILT_IN_MEMCMP, "memcmp"); - builtin_function ("__builtin_memset", memset_ftype, - BUILT_IN_MEMSET, "memset"); - builtin_function ("__builtin_strcmp", int_ftype_string_string, - BUILT_IN_STRCMP, "strcmp"); - builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr, - BUILT_IN_STRCPY, "strcpy"); - builtin_function ("__builtin_strlen", strlen_ftype, - BUILT_IN_STRLEN, "strlen"); - builtin_function ("__builtin_sqrtf", float_ftype_float, - BUILT_IN_FSQRT, "sqrtf"); - builtin_function ("__builtin_fsqrt", double_ftype_double, - BUILT_IN_FSQRT, "sqrt"); - builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble, - BUILT_IN_FSQRT, "sqrtl"); - builtin_function ("__builtin_sinf", float_ftype_float, - BUILT_IN_SIN, "sinf"); - builtin_function ("__builtin_sin", double_ftype_double, - BUILT_IN_SIN, "sin"); - builtin_function ("__builtin_sinl", ldouble_ftype_ldouble, - BUILT_IN_SIN, "sinl"); - builtin_function ("__builtin_cosf", float_ftype_float, - BUILT_IN_COS, "cosf"); - builtin_function ("__builtin_cos", double_ftype_double, - BUILT_IN_COS, "cos"); - builtin_function ("__builtin_cosl", ldouble_ftype_ldouble, - BUILT_IN_COS, "cosl"); - builtin_function ("__builtin_setjmp", - build_function_type (integer_type_node, - tree_cons (NULL_TREE, - ptr_type_node, endlink)), - BUILT_IN_SETJMP, NULL_PTR); - builtin_function ("__builtin_longjmp", - build_function_type - (void_type_node, - tree_cons (NULL, ptr_type_node, - tree_cons (NULL_TREE, - integer_type_node, - endlink))), - BUILT_IN_LONGJMP, NULL_PTR); - builtin_function ("__builtin_trap", - build_function_type (void_type_node, endlink), - BUILT_IN_TRAP, NULL_PTR); - - /* In an ANSI C program, it is okay to supply built-in meanings - for these functions, since applications cannot validly use them - with any other meaning. - However, honor the -fno-builtin option. */ - if (!flag_no_builtin) - { - builtin_function ("abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR); - builtin_function ("fabsf", float_ftype_float, BUILT_IN_FABS, NULL_PTR); - builtin_function ("fabs", double_ftype_double, BUILT_IN_FABS, NULL_PTR); - builtin_function ("fabsl", ldouble_ftype_ldouble, BUILT_IN_FABS, - NULL_PTR); - builtin_function ("labs", long_ftype_long, BUILT_IN_LABS, NULL_PTR); - builtin_function ("memcpy", memcpy_ftype, BUILT_IN_MEMCPY, NULL_PTR); - builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP, - NULL_PTR); - builtin_function ("memset", memset_ftype, BUILT_IN_MEMSET, NULL_PTR); - builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, - NULL_PTR); - builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, - NULL_PTR); - builtin_function ("strlen", strlen_ftype, BUILT_IN_STRLEN, NULL_PTR); - builtin_function ("sqrtf", float_ftype_float, BUILT_IN_FSQRT, NULL_PTR); - builtin_function ("sqrt", double_ftype_double, BUILT_IN_FSQRT, NULL_PTR); - builtin_function ("sqrtl", ldouble_ftype_ldouble, BUILT_IN_FSQRT, - NULL_PTR); - builtin_function ("sinf", float_ftype_float, BUILT_IN_SIN, NULL_PTR); - builtin_function ("sin", double_ftype_double, BUILT_IN_SIN, NULL_PTR); - builtin_function ("sinl", ldouble_ftype_ldouble, BUILT_IN_SIN, NULL_PTR); - builtin_function ("cosf", float_ftype_float, BUILT_IN_COS, NULL_PTR); - builtin_function ("cos", double_ftype_double, BUILT_IN_COS, NULL_PTR); - builtin_function ("cosl", ldouble_ftype_ldouble, BUILT_IN_COS, NULL_PTR); - - /* Declare these functions volatile - to avoid spurious "control drops through" warnings. */ - /* Don't specify the argument types, to avoid errors - from certain code which isn't valid in ANSI but which exists. */ - temp = builtin_function ("abort", void_ftype_any, NOT_BUILT_IN, - NULL_PTR); - TREE_THIS_VOLATILE (temp) = 1; - TREE_SIDE_EFFECTS (temp) = 1; - temp = builtin_function ("exit", void_ftype_any, NOT_BUILT_IN, NULL_PTR); - TREE_THIS_VOLATILE (temp) = 1; - TREE_SIDE_EFFECTS (temp) = 1; - } - -#if 0 - /* Support for these has not been written in either expand_builtin - or build_function_call. */ - builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, NULL_PTR); - builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, NULL_PTR); - builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR, - NULL_PTR); - builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL, - NULL_PTR); - builtin_function ("__builtin_fmod", double_ftype_double_double, - BUILT_IN_FMOD, NULL_PTR); - builtin_function ("__builtin_frem", double_ftype_double_double, - BUILT_IN_FREM, NULL_PTR); - builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP, - NULL_PTR); - builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN, - NULL_PTR); -#endif - - pedantic_lvalues = pedantic; - - /* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */ - declare_function_name (); - - start_identifier_warnings (); - - /* Prepare to check format strings against argument lists. */ - init_function_format_info (); - - init_iterators (); - - incomplete_decl_finalize_hook = finish_incomplete_decl; - - lang_get_alias_set = c_get_alias_set; -} - -/* Return a definition for a builtin function named NAME and whose data type - is TYPE. TYPE should be a function type with argument types. - FUNCTION_CODE tells later passes how to compile calls to this function. - See tree.h for its possible values. - - If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME, - the name to be called if we can't opencode the function. */ - -tree -builtin_function (name, type, function_code, library_name) - const char *name; - tree type; - enum built_in_function function_code; - const char *library_name; -{ - tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type); - DECL_EXTERNAL (decl) = 1; - TREE_PUBLIC (decl) = 1; - /* If -traditional, permit redefining a builtin function any way you like. - (Though really, if the program redefines these functions, - it probably won't work right unless compiled with -fno-builtin.) */ - if (flag_traditional && name[0] != '_') - DECL_BUILT_IN_NONANSI (decl) = 1; - if (library_name) - DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name); - make_decl_rtl (decl, NULL_PTR, 1); - pushdecl (decl); - if (function_code != NOT_BUILT_IN) - { - DECL_BUILT_IN (decl) = 1; - DECL_FUNCTION_CODE (decl) = function_code; - } - /* Warn if a function in the namespace for users - is used without an occasion to consider it declared. */ - if (name[0] != '_' || name[1] != '_') - C_DECL_ANTICIPATED (decl) = 1; - - return decl; -} - -/* Called when a declaration is seen that contains no names to declare. - If its type is a reference to a structure, union or enum inherited - from a containing scope, shadow that tag name for the current scope - with a forward reference. - If its type defines a new named structure or union - or defines an enum, it is valid but we need not do anything here. - Otherwise, it is an error. */ - -void -shadow_tag (declspecs) - tree declspecs; -{ - shadow_tag_warned (declspecs, 0); -} - -void -shadow_tag_warned (declspecs, warned) - tree declspecs; - int warned; - /* 1 => we have done a pedwarn. 2 => we have done a warning, but - no pedwarn. */ -{ - int found_tag = 0; - register tree link; - tree specs, attrs; - - pending_invalid_xref = 0; - - /* Remove the attributes from declspecs, since they will confuse the - following code. */ - split_specs_attrs (declspecs, &specs, &attrs); - - for (link = specs; link; link = TREE_CHAIN (link)) - { - register tree value = TREE_VALUE (link); - register enum tree_code code = TREE_CODE (value); - - if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE) - /* Used to test also that TYPE_SIZE (value) != 0. - That caused warning for `struct foo;' at top level in the file. */ - { - register tree name = lookup_tag_reverse (value); - register tree t; - - found_tag++; - - if (name == 0) - { - if (warned != 1 && code != ENUMERAL_TYPE) - /* Empty unnamed enum OK */ - { - pedwarn ("unnamed struct/union that defines no instances"); - warned = 1; - } - } - else - { - t = lookup_tag (code, name, current_binding_level, 1); - - if (t == 0) - { - t = make_node (code); - pushtag (name, t); - } - } - } - else - { - if (!warned && ! in_system_header) - { - warning ("useless keyword or type name in empty declaration"); - warned = 2; - } - } - } - - if (found_tag > 1) - error ("two types specified in one empty declaration"); - - if (warned != 1) - { - if (found_tag == 0) - pedwarn ("empty declaration"); - } -} - -/* Decode a "typename", such as "int **", returning a ..._TYPE node. */ - -tree -groktypename (typename) - tree typename; -{ - if (TREE_CODE (typename) != TREE_LIST) - return typename; - return grokdeclarator (TREE_VALUE (typename), - TREE_PURPOSE (typename), - TYPENAME, 0); -} - -/* Return a PARM_DECL node for a given pair of specs and declarator. */ - -tree -groktypename_in_parm_context (typename) - tree typename; -{ - if (TREE_CODE (typename) != TREE_LIST) - return typename; - return grokdeclarator (TREE_VALUE (typename), - TREE_PURPOSE (typename), - PARM, 0); -} - -/* Decode a declarator in an ordinary declaration or data definition. - This is called as soon as the type information and variable name - have been parsed, before parsing the initializer if any. - Here we create the ..._DECL node, fill in its type, - and put it on the list of decls for the current context. - The ..._DECL node is returned as the value. - - Exception: for arrays where the length is not specified, - the type is left null, to be filled in by `finish_decl'. - - Function definitions do not come here; they go to start_function - instead. However, external and forward declarations of functions - do go through here. Structure field declarations are done by - grokfield and not through here. */ - -/* Set this to zero to debug not using the temporary obstack - to parse initializers. */ -int debug_temp_inits = 1; - -tree -start_decl (declarator, declspecs, initialized, attributes, prefix_attributes) - tree declarator, declspecs; - int initialized; - tree attributes, prefix_attributes; -{ - register tree decl = grokdeclarator (declarator, declspecs, - NORMAL, initialized); - register tree tem; - int init_written = initialized; - - /* The corresponding pop_obstacks is in finish_decl. */ - push_obstacks_nochange (); - - if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL - && !strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "main")) - warning_with_decl (decl, "`%s' is usually a function"); - - if (initialized) - /* Is it valid for this decl to have an initializer at all? - If not, set INITIALIZED to zero, which will indirectly - tell `finish_decl' to ignore the initializer once it is parsed. */ - switch (TREE_CODE (decl)) - { - case TYPE_DECL: - /* typedef foo = bar means give foo the same type as bar. - We haven't parsed bar yet, so `finish_decl' will fix that up. - Any other case of an initialization in a TYPE_DECL is an error. */ - if (pedantic || list_length (declspecs) > 1) - { - error ("typedef `%s' is initialized", - IDENTIFIER_POINTER (DECL_NAME (decl))); - initialized = 0; - } - break; - - case FUNCTION_DECL: - error ("function `%s' is initialized like a variable", - IDENTIFIER_POINTER (DECL_NAME (decl))); - initialized = 0; - break; - - case PARM_DECL: - /* DECL_INITIAL in a PARM_DECL is really DECL_ARG_TYPE. */ - error ("parameter `%s' is initialized", - IDENTIFIER_POINTER (DECL_NAME (decl))); - initialized = 0; - break; - - default: - /* Don't allow initializations for incomplete types - except for arrays which might be completed by the initialization. */ - if (TYPE_SIZE (TREE_TYPE (decl)) != 0) - { - /* A complete type is ok if size is fixed. */ - - if (TREE_CODE (TYPE_SIZE (TREE_TYPE (decl))) != INTEGER_CST - || C_DECL_VARIABLE_SIZE (decl)) - { - error ("variable-sized object may not be initialized"); - initialized = 0; - } - } - else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE) - { - error ("variable `%s' has initializer but incomplete type", - IDENTIFIER_POINTER (DECL_NAME (decl))); - initialized = 0; - } - else if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl))) == 0) - { - error ("elements of array `%s' have incomplete type", - IDENTIFIER_POINTER (DECL_NAME (decl))); - initialized = 0; - } - } - - if (initialized) - { -#if 0 /* Seems redundant with grokdeclarator. */ - if (current_binding_level != global_binding_level - && DECL_EXTERNAL (decl) - && TREE_CODE (decl) != FUNCTION_DECL) - warning ("declaration of `%s' has `extern' and is initialized", - IDENTIFIER_POINTER (DECL_NAME (decl))); -#endif - DECL_EXTERNAL (decl) = 0; - if (current_binding_level == global_binding_level) - TREE_STATIC (decl) = 1; - - /* Tell `pushdecl' this is an initialized decl - even though we don't yet have the initializer expression. - Also tell `finish_decl' it may store the real initializer. */ - DECL_INITIAL (decl) = error_mark_node; - } - - /* If this is a function declaration, write a record describing it to the - prototypes file (if requested). */ - - if (TREE_CODE (decl) == FUNCTION_DECL) - gen_aux_info_record (decl, 0, 0, TYPE_ARG_TYPES (TREE_TYPE (decl)) != 0); - - /* ANSI specifies that a tentative definition which is not merged with - a non-tentative definition behaves exactly like a definition with an - initializer equal to zero. (Section 3.7.2) - -fno-common gives strict ANSI behavior. Usually you don't want it. - This matters only for variables with external linkage. */ - 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); - - /* Add this decl to the current binding level. - TEM may equal DECL or it may be a previous decl of the same name. */ - tem = pushdecl (decl); - - /* For a local variable, define the RTL now. */ - if (current_binding_level != global_binding_level - /* But not if this is a duplicate decl - and we preserved the rtl from the previous one - (which may or may not happen). */ - && DECL_RTL (tem) == 0) - { - if (TYPE_SIZE (TREE_TYPE (tem)) != 0) - expand_decl (tem); - else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE - && DECL_INITIAL (tem) != 0) - expand_decl (tem); - } - - if (init_written) - { - /* When parsing and digesting the initializer, - use temporary storage. Do this even if we will ignore the value. */ - if (current_binding_level == global_binding_level && debug_temp_inits) - temporary_allocation (); - } - - return tem; -} - -/* Finish processing of a declaration; - install its initial value. - If the length of an array type is not known before, - it must be determined now, from the initial value, or it is an error. */ - -void -finish_decl (decl, init, asmspec_tree) - tree decl, init; - tree asmspec_tree; -{ - register tree type = TREE_TYPE (decl); - int was_incomplete = (DECL_SIZE (decl) == 0); - int temporary = allocation_temporary_p (); - char *asmspec = 0; - - /* If a name was specified, get the string. */ - if (asmspec_tree) - asmspec = TREE_STRING_POINTER (asmspec_tree); - - /* If `start_decl' didn't like having an initialization, ignore it now. */ - - if (init != 0 && DECL_INITIAL (decl) == 0) - init = 0; - /* Don't crash if parm is initialized. */ - if (TREE_CODE (decl) == PARM_DECL) - init = 0; - - if (ITERATOR_P (decl)) - { - if (init == 0) - error_with_decl (decl, "iterator has no initial value"); - else - init = save_expr (init); - } - - if (init) - { - if (TREE_CODE (decl) != TYPE_DECL) - store_init_value (decl, init); - else - { - /* typedef foo = bar; store the type of bar as the type of foo. */ - TREE_TYPE (decl) = TREE_TYPE (init); - DECL_INITIAL (decl) = init = 0; - } - } - - /* Pop back to the obstack that is current for this binding level. - This is because MAXINDEX, rtl, etc. to be made below - must go in the permanent obstack. But don't discard the - temporary data yet. */ - pop_obstacks (); -#if 0 /* pop_obstacks was near the end; this is what was here. */ - if (current_binding_level == global_binding_level && temporary) - end_temporary_allocation (); -#endif - - /* Deduce size of array from initialization, if not already known */ - - if (TREE_CODE (type) == ARRAY_TYPE - && TYPE_DOMAIN (type) == 0 - && TREE_CODE (decl) != TYPE_DECL) - { - int do_default - = (TREE_STATIC (decl) - /* Even if pedantic, an external linkage array - may have incomplete type at first. */ - ? pedantic && !TREE_PUBLIC (decl) - : !DECL_EXTERNAL (decl)); - int failure - = complete_array_type (type, DECL_INITIAL (decl), do_default); - - /* Get the completed type made by complete_array_type. */ - type = TREE_TYPE (decl); - - if (failure == 1) - error_with_decl (decl, "initializer fails to determine size of `%s'"); - - if (failure == 2) - { - if (do_default) - error_with_decl (decl, "array size missing in `%s'"); - /* If a `static' var's size isn't known, - make it extern as well as static, so it does not get - allocated. - If it is not `static', then do not mark extern; - finish_incomplete_decl will give it a default size - and it will get allocated. */ - else if (!pedantic && TREE_STATIC (decl) && ! TREE_PUBLIC (decl)) - DECL_EXTERNAL (decl) = 1; - } - - /* TYPE_MAX_VALUE is always one less than the number of elements - in the array, because we start counting at zero. Therefore, - warn only if the value is less than zero. */ - if (pedantic && TYPE_DOMAIN (type) != 0 - && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0) - error_with_decl (decl, "zero or negative size array `%s'"); - - layout_decl (decl, 0); - } - - if (TREE_CODE (decl) == VAR_DECL) - { - if (DECL_SIZE (decl) == 0 - && TYPE_SIZE (TREE_TYPE (decl)) != 0) - layout_decl (decl, 0); - - if (DECL_SIZE (decl) == 0 - && (TREE_STATIC (decl) - ? - /* A static variable with an incomplete type - is an error if it is initialized. - Also if it is not file scope. - Otherwise, let it through, but if it is not `extern' - then it may cause an error message later. */ - /* A duplicate_decls call could have changed an extern - declaration into a file scope one. This can be detected - by TREE_ASM_WRITTEN being set. */ - (DECL_INITIAL (decl) != 0 - || (DECL_CONTEXT (decl) != 0 && ! TREE_ASM_WRITTEN (decl))) - : - /* An automatic variable with an incomplete type - is an error. */ - !DECL_EXTERNAL (decl))) - { - error_with_decl (decl, "storage size of `%s' isn't known"); - TREE_TYPE (decl) = error_mark_node; - } - - if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl)) - && DECL_SIZE (decl) != 0) - { - if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST) - constant_expression_warning (DECL_SIZE (decl)); - else - error_with_decl (decl, "storage size of `%s' isn't constant"); - } - - if (TREE_USED (type)) - TREE_USED (decl) = 1; - } - - /* If this is a function and an assembler name is specified, it isn't - builtin any more. Also reset DECL_RTL so we can give it its new - name. */ - if (TREE_CODE (decl) == FUNCTION_DECL && asmspec) - { - DECL_BUILT_IN (decl) = 0; - DECL_RTL (decl) = 0; - } - - /* Output the assembler code and/or RTL code for variables and functions, - unless the type is an undefined structure or union. - If not, it will get done when the type is completed. */ - - if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL) - { - if ((flag_traditional || TREE_PERMANENT (decl)) - && allocation_temporary_p ()) - { - push_obstacks_nochange (); - end_temporary_allocation (); - /* This is a no-op in c-lang.c or something real in objc-actions.c. */ - maybe_objc_check_decl (decl); - rest_of_decl_compilation (decl, asmspec, - (DECL_CONTEXT (decl) == 0 - || TREE_ASM_WRITTEN (decl)), - 0); - pop_obstacks (); - } - else - { - /* This is a no-op in c-lang.c or something real in objc-actions.c. */ - maybe_objc_check_decl (decl); - rest_of_decl_compilation (decl, asmspec, DECL_CONTEXT (decl) == 0, - 0); - } - if (DECL_CONTEXT (decl) != 0) - { - /* Recompute the RTL of a local array now - if it used to be an incomplete type. */ - if (was_incomplete - && ! TREE_STATIC (decl) && ! DECL_EXTERNAL (decl)) - { - /* If we used it already as memory, it must stay in memory. */ - TREE_ADDRESSABLE (decl) = TREE_USED (decl); - /* If it's still incomplete now, no init will save it. */ - if (DECL_SIZE (decl) == 0) - DECL_INITIAL (decl) = 0; - expand_decl (decl); - } - /* Compute and store the initial value. */ - if (TREE_CODE (decl) != FUNCTION_DECL) - expand_decl_init (decl); - } - } - - if (TREE_CODE (decl) == TYPE_DECL) - { - /* This is a no-op in c-lang.c or something real in objc-actions.c. */ - maybe_objc_check_decl (decl); - rest_of_decl_compilation (decl, NULL_PTR, DECL_CONTEXT (decl) == 0, - 0); - } - - /* ??? After 2.3, test (init != 0) instead of TREE_CODE. */ - /* This test used to include TREE_PERMANENT, however, we have the same - problem with initializers at the function level. Such initializers get - saved until the end of the function on the momentary_obstack. */ - if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl)) - && temporary - /* DECL_INITIAL is not defined in PARM_DECLs, since it shares - space with DECL_ARG_TYPE. */ - && TREE_CODE (decl) != PARM_DECL) - { - /* We need to remember that this array HAD an initialization, - but discard the actual temporary nodes, - since we can't have a permanent node keep pointing to them. */ - /* We make an exception for inline functions, since it's - normal for a local extern redeclaration of an inline function - to have a copy of the top-level decl's DECL_INLINE. */ - if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node) - { - /* If this is a const variable, then preserve the - initializer instead of discarding it so that we can optimize - references to it. */ - /* This test used to include TREE_STATIC, but this won't be set - for function level initializers. */ - if (TREE_READONLY (decl) || ITERATOR_P (decl)) - { - preserve_initializer (); - /* Hack? Set the permanent bit for something that is permanent, - but not on the permanent obstack, so as to convince - output_constant_def to make its rtl on the permanent - obstack. */ - TREE_PERMANENT (DECL_INITIAL (decl)) = 1; - - /* The initializer and DECL must have the same (or equivalent - types), but if the initializer is a STRING_CST, its type - might not be on the right obstack, so copy the type - of DECL. */ - TREE_TYPE (DECL_INITIAL (decl)) = type; - } - else - DECL_INITIAL (decl) = error_mark_node; - } - } - - /* If requested, warn about definitions of large data objects. */ - - if (warn_larger_than - && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL) - && !DECL_EXTERNAL (decl)) - { - register tree decl_size = DECL_SIZE (decl); - - if (decl_size && TREE_CODE (decl_size) == INTEGER_CST) - { - unsigned units = TREE_INT_CST_LOW(decl_size) / BITS_PER_UNIT; - - if (units > larger_than_size) - warning_with_decl (decl, "size of `%s' is %u bytes", units); - } - } - -#if 0 - /* Resume permanent allocation, if not within a function. */ - /* The corresponding push_obstacks_nochange is in start_decl, - and in push_parm_decl and in grokfield. */ - pop_obstacks (); -#endif - - /* If we have gone back from temporary to permanent allocation, - actually free the temporary space that we no longer need. */ - if (temporary && !allocation_temporary_p ()) - permanent_allocation (0); - - /* At the end of a declaration, throw away any variable type sizes - of types defined inside that declaration. There is no use - computing them in the following function definition. */ - if (current_binding_level == global_binding_level) - get_pending_sizes (); -} - -/* If DECL has a cleanup, build and return that cleanup here. - This is a callback called by expand_expr. */ - -tree -maybe_build_cleanup (decl) - tree decl ATTRIBUTE_UNUSED; -{ - /* There are no cleanups in C. */ - return NULL_TREE; -} - -/* Given a parsed parameter declaration, - decode it into a PARM_DECL and push that on the current binding level. - Also, for the sake of forward parm decls, - record the given order of parms in `parm_order'. */ - -void -push_parm_decl (parm) - tree parm; -{ - tree decl; - int old_immediate_size_expand = immediate_size_expand; - /* Don't try computing parm sizes now -- wait till fn is called. */ - immediate_size_expand = 0; - - /* The corresponding pop_obstacks is in finish_decl. */ - push_obstacks_nochange (); - - 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))); - -#if 0 - if (DECL_NAME (decl)) - { - tree olddecl; - olddecl = lookup_name (DECL_NAME (decl)); - if (pedantic && olddecl != 0 && TREE_CODE (olddecl) == TYPE_DECL) - pedwarn_with_decl (decl, "ANSI C forbids parameter `%s' shadowing typedef"); - } -#endif - - decl = pushdecl (decl); - - immediate_size_expand = old_immediate_size_expand; - - current_binding_level->parm_order - = tree_cons (NULL_TREE, decl, current_binding_level->parm_order); - - /* Add this decl to the current binding level. */ - finish_decl (decl, NULL_TREE, NULL_TREE); -} - -/* Clear the given order of parms in `parm_order'. - Used at start of parm list, - and also at semicolon terminating forward decls. */ - -void -clear_parm_order () -{ - current_binding_level->parm_order = NULL_TREE; -} - -/* Make TYPE a complete type based on INITIAL_VALUE. - Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered, - 2 if there was no information (in which case assume 1 if DO_DEFAULT). */ - -int -complete_array_type (type, initial_value, do_default) - tree type; - tree initial_value; - int do_default; -{ - register tree maxindex = NULL_TREE; - int value = 0; - - if (initial_value) - { - /* Note MAXINDEX is really the maximum index, - one less than the size. */ - if (TREE_CODE (initial_value) == STRING_CST) - { - int eltsize - = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value))); - maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value) - / eltsize) - 1, 0); - } - else if (TREE_CODE (initial_value) == CONSTRUCTOR) - { - tree elts = CONSTRUCTOR_ELTS (initial_value); - maxindex = size_binop (MINUS_EXPR, integer_zero_node, size_one_node); - for (; elts; elts = TREE_CHAIN (elts)) - { - if (TREE_PURPOSE (elts)) - maxindex = TREE_PURPOSE (elts); - else - maxindex = size_binop (PLUS_EXPR, maxindex, size_one_node); - } - maxindex = copy_node (maxindex); - } - else - { - /* Make an error message unless that happened already. */ - if (initial_value != error_mark_node) - value = 1; - - /* Prevent further error messages. */ - maxindex = build_int_2 (0, 0); - } - } - - if (!maxindex) - { - if (do_default) - maxindex = build_int_2 (0, 0); - value = 2; - } - - if (maxindex) - { - TYPE_DOMAIN (type) = build_index_type (maxindex); - if (!TREE_TYPE (maxindex)) - TREE_TYPE (maxindex) = TYPE_DOMAIN (type); - } - - /* Lay out the type now that we can get the real answer. */ - - layout_type (type); - - return value; -} - -/* Given declspecs and a declarator, - determine the name and type of the object declared - and construct a ..._DECL node for it. - (In one case we can return a ..._TYPE node instead. - For invalid input we sometimes return 0.) - - DECLSPECS is a chain of tree_list nodes whose value fields - are the storage classes and type specifiers. - - DECL_CONTEXT says which syntactic context this declaration is in: - NORMAL for most contexts. Make a VAR_DECL or FUNCTION_DECL or TYPE_DECL. - FUNCDEF for a function definition. Like NORMAL but a few different - error messages in each case. Return value may be zero meaning - this definition is too screwy to try to parse. - PARM for a parameter declaration (either within a function prototype - or before a function body). Make a PARM_DECL, or return void_type_node. - TYPENAME if for a typename (in a cast or sizeof). - Don't make a DECL node; just return the ..._TYPE node. - FIELD for a struct or union field; make a FIELD_DECL. - BITFIELD for a field with specified width. - INITIALIZED is 1 if the decl has an initializer. - - In the TYPENAME case, DECLARATOR is really an absolute declarator. - It may also be so in the PARM case, for a prototype where the - argument type is specified but not the name. - - This function is where the complicated C meanings of `static' - and `extern' are interpreted. */ - -static tree -grokdeclarator (declarator, declspecs, decl_context, initialized) - tree declspecs; - tree declarator; - enum decl_context decl_context; - int initialized; -{ - int specbits = 0; - tree spec; - tree type = NULL_TREE; - int longlong = 0; - int constp; - int restrictp; - int volatilep; - int type_quals = TYPE_UNQUALIFIED; - int inlinep; - int explicit_int = 0; - int explicit_char = 0; - int defaulted_int = 0; - tree typedef_decl = 0; - const char *name; - tree typedef_type = 0; - int funcdef_flag = 0; - enum tree_code innermost_code = ERROR_MARK; - int bitfield = 0; - int size_varies = 0; - tree decl_machine_attr = NULL_TREE; - - if (decl_context == BITFIELD) - bitfield = 1, decl_context = FIELD; - - if (decl_context == FUNCDEF) - funcdef_flag = 1, decl_context = NORMAL; - - push_obstacks_nochange (); - - if (flag_traditional && allocation_temporary_p ()) - end_temporary_allocation (); - - /* Look inside a declarator for the name being declared - and get it as a string, for an error message. */ - { - register tree decl = declarator; - name = 0; - - while (decl) - switch (TREE_CODE (decl)) - { - case ARRAY_REF: - case INDIRECT_REF: - case CALL_EXPR: - innermost_code = TREE_CODE (decl); - decl = TREE_OPERAND (decl, 0); - break; - - case IDENTIFIER_NODE: - name = IDENTIFIER_POINTER (decl); - decl = 0; - break; - - default: - abort (); - } - if (name == 0) - name = "type name"; - } - - /* A function definition's declarator must have the form of - a function declarator. */ - - if (funcdef_flag && innermost_code != CALL_EXPR) - return 0; - - /* Anything declared one level down from the top level - must be one of the parameters of a function - (because the body is at least two levels down). */ - - /* If this looks like a function definition, make it one, - even if it occurs where parms are expected. - Then store_parm_decls will reject it and not use it as a parm. */ - if (decl_context == NORMAL && !funcdef_flag - && current_binding_level->parm_flag) - decl_context = PARM; - - /* Look through the decl specs and record which ones appear. - Some typespecs are defined as built-in typenames. - Others, the ones that are modifiers of other types, - are represented by bits in SPECBITS: set the bits for - the modifiers that appear. Storage class keywords are also in SPECBITS. - - If there is a typedef name or a type, store the type in TYPE. - This includes builtin typedefs such as `int'. - - Set EXPLICIT_INT or EXPLICIT_CHAR if the type is `int' or `char' - and did not come from a user typedef. - - Set LONGLONG if `long' is mentioned twice. */ - - for (spec = declspecs; spec; spec = TREE_CHAIN (spec)) - { - register int i; - register tree id = TREE_VALUE (spec); - - if (id == ridpointers[(int) RID_INT]) - explicit_int = 1; - if (id == ridpointers[(int) RID_CHAR]) - explicit_char = 1; - - if (TREE_CODE (id) == IDENTIFIER_NODE) - for (i = (int) RID_FIRST_MODIFIER; i < (int) RID_MAX; i++) - { - if (ridpointers[i] == id) - { - if (i == (int) RID_LONG && specbits & (1<<i)) - { - if (longlong) - error ("`long long long' is too long for GCC"); - else - { - if (pedantic && ! in_system_header && warn_long_long) - pedwarn ("ANSI C does not support `long long'"); - longlong = 1; - } - } - else if (specbits & (1 << i)) - pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); - specbits |= 1 << i; - goto found; - } - } - if (type) - error ("two or more data types in declaration of `%s'", name); - /* Actual typedefs come to us as TYPE_DECL nodes. */ - else if (TREE_CODE (id) == TYPE_DECL) - { - type = TREE_TYPE (id); - decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id); - typedef_decl = id; - } - /* Built-in types come as identifiers. */ - else if (TREE_CODE (id) == IDENTIFIER_NODE) - { - register tree t = lookup_name (id); - if (TREE_TYPE (t) == error_mark_node) - ; - else if (!t || TREE_CODE (t) != TYPE_DECL) - error ("`%s' fails to be a typedef or built in type", - IDENTIFIER_POINTER (id)); - else - { - type = TREE_TYPE (t); - typedef_decl = t; - } - } - else if (TREE_CODE (id) != ERROR_MARK) - type = id; - - found: {} - } - - typedef_type = type; - if (type) - size_varies = C_TYPE_VARIABLE_SIZE (type); - - /* No type at all: default to `int', and set DEFAULTED_INT - because it was not a user-defined typedef. */ - - if (type == 0) - { - if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) - | (1 << (int) RID_SIGNED) - | (1 << (int) RID_UNSIGNED)))) - /* Don't warn about typedef foo = bar. */ - && ! (specbits & (1 << (int) RID_TYPEDEF) && initialized) - && ! (in_system_header && ! allocation_temporary_p ())) - { - /* Issue a warning if this is an ISO C 9x program or if -Wreturn-type - and this is a function, or if -Wimplicit; prefer the former - warning since it is more explicit. */ - if ((warn_implicit_int || warn_return_type) && funcdef_flag) - warn_about_return_type = 1; - else if (warn_implicit_int || flag_isoc9x) - warning ("type defaults to `int' in declaration of `%s'", name); - } - - defaulted_int = 1; - type = integer_type_node; - } - - /* Now process the modifiers that were specified - and check for invalid combinations. */ - - /* Long double is a special combination. */ - - if ((specbits & 1 << (int) RID_LONG) && ! longlong - && TYPE_MAIN_VARIANT (type) == double_type_node) - { - specbits &= ~ (1 << (int) RID_LONG); - type = long_double_type_node; - } - - /* Check all other uses of type modifiers. */ - - if (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) - | (1 << (int) RID_UNSIGNED) | (1 << (int) RID_SIGNED))) - { - int ok = 0; - - if ((specbits & 1 << (int) RID_LONG) - && (specbits & 1 << (int) RID_SHORT)) - error ("both long and short specified for `%s'", name); - else if (((specbits & 1 << (int) RID_LONG) - || (specbits & 1 << (int) RID_SHORT)) - && explicit_char) - error ("long or short specified with char for `%s'", name); - else if (((specbits & 1 << (int) RID_LONG) - || (specbits & 1 << (int) RID_SHORT)) - && TREE_CODE (type) == REAL_TYPE) - { - static int already = 0; - - error ("long or short specified with floating type for `%s'", name); - if (! already && ! pedantic) - { - error ("the only valid combination is `long double'"); - already = 1; - } - } - else if ((specbits & 1 << (int) RID_SIGNED) - && (specbits & 1 << (int) RID_UNSIGNED)) - error ("both signed and unsigned specified for `%s'", name); - else if (TREE_CODE (type) != INTEGER_TYPE) - error ("long, short, signed or unsigned invalid for `%s'", name); - else - { - ok = 1; - if (!explicit_int && !defaulted_int && !explicit_char && pedantic) - { - pedwarn ("long, short, signed or unsigned used invalidly for `%s'", - name); - if (flag_pedantic_errors) - ok = 0; - } - } - - /* Discard the type modifiers if they are invalid. */ - if (! ok) - { - specbits &= ~((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) - | (1 << (int) RID_UNSIGNED) | (1 << (int) RID_SIGNED)); - longlong = 0; - } - } - - if ((specbits & (1 << (int) RID_COMPLEX)) - && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE) - { - error ("complex invalid for `%s'", name); - specbits &= ~ (1 << (int) RID_COMPLEX); - } - - /* Decide whether an integer type is signed or not. - Optionally treat bitfields as signed by default. */ - if (specbits & 1 << (int) RID_UNSIGNED - /* Traditionally, all bitfields are unsigned. */ - || (bitfield && flag_traditional - && (! explicit_flag_signed_bitfields || !flag_signed_bitfields)) - || (bitfield && ! flag_signed_bitfields - && (explicit_int || defaulted_int || explicit_char - /* A typedef for plain `int' without `signed' - can be controlled just like plain `int'. */ - || ! (typedef_decl != 0 - && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))) - && TREE_CODE (type) != ENUMERAL_TYPE - && !(specbits & 1 << (int) RID_SIGNED))) - { - if (longlong) - type = long_long_unsigned_type_node; - else if (specbits & 1 << (int) RID_LONG) - type = long_unsigned_type_node; - else if (specbits & 1 << (int) RID_SHORT) - type = short_unsigned_type_node; - else if (type == char_type_node) - type = unsigned_char_type_node; - else if (typedef_decl) - type = unsigned_type (type); - else - type = unsigned_type_node; - } - else if ((specbits & 1 << (int) RID_SIGNED) - && type == char_type_node) - type = signed_char_type_node; - else if (longlong) - type = long_long_integer_type_node; - else if (specbits & 1 << (int) RID_LONG) - type = long_integer_type_node; - else if (specbits & 1 << (int) RID_SHORT) - type = short_integer_type_node; - - if (specbits & 1 << (int) RID_COMPLEX) - { - /* If we just have "complex", it is equivalent to - "complex double", but if any modifiers at all are specified it is - the complex form of TYPE. E.g, "complex short" is - "complex short int". */ - - if (defaulted_int && ! longlong - && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) - | (1 << (int) RID_SIGNED) - | (1 << (int) RID_UNSIGNED)))) - type = complex_double_type_node; - else if (type == integer_type_node) - type = complex_integer_type_node; - else if (type == float_type_node) - type = complex_float_type_node; - else if (type == double_type_node) - type = complex_double_type_node; - else if (type == long_double_type_node) - type = complex_long_double_type_node; - else - type = build_complex_type (type); - } - - /* Figure out the type qualifiers for the declaration. There are - two ways a declaration can become qualified. One is something - like `const int i' where the `const' is explicit. Another is - something like `typedef const int CI; CI i' where the type of the - declaration contains the `const'. */ - constp = !! (specbits & 1 << (int) RID_CONST) + TYPE_READONLY (type); - restrictp = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (type); - volatilep = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (type); - inlinep = !! (specbits & (1 << (int) RID_INLINE)); - if (constp > 1) - pedwarn ("duplicate `const'"); - if (restrictp > 1) - pedwarn ("duplicate `restrict'"); - if (volatilep > 1) - pedwarn ("duplicate `volatile'"); - if (! flag_gen_aux_info && (TYPE_QUALS (type))) - type = TYPE_MAIN_VARIANT (type); - type_quals = ((constp ? TYPE_QUAL_CONST : 0) - | (restrictp ? TYPE_QUAL_RESTRICT : 0) - | (volatilep ? TYPE_QUAL_VOLATILE : 0)); - - /* Warn if two storage classes are given. Default to `auto'. */ - - { - int nclasses = 0; - - if (specbits & 1 << (int) RID_AUTO) nclasses++; - if (specbits & 1 << (int) RID_STATIC) nclasses++; - if (specbits & 1 << (int) RID_EXTERN) nclasses++; - if (specbits & 1 << (int) RID_REGISTER) nclasses++; - if (specbits & 1 << (int) RID_TYPEDEF) nclasses++; - if (specbits & 1 << (int) RID_ITERATOR) nclasses++; - - /* Warn about storage classes that are invalid for certain - kinds of declarations (parameters, typenames, etc.). */ - - if (nclasses > 1) - error ("multiple storage classes in declaration of `%s'", name); - else if (funcdef_flag - && (specbits - & ((1 << (int) RID_REGISTER) - | (1 << (int) RID_AUTO) - | (1 << (int) RID_TYPEDEF)))) - { - if (specbits & 1 << (int) RID_AUTO - && (pedantic || current_binding_level == global_binding_level)) - pedwarn ("function definition declared `auto'"); - if (specbits & 1 << (int) RID_REGISTER) - error ("function definition declared `register'"); - if (specbits & 1 << (int) RID_TYPEDEF) - error ("function definition declared `typedef'"); - specbits &= ~ ((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER) - | (1 << (int) RID_AUTO)); - } - else if (decl_context != NORMAL && nclasses > 0) - { - if (decl_context == PARM && specbits & 1 << (int) RID_REGISTER) - ; - else - { - error ((decl_context == FIELD - ? "storage class specified for structure field `%s'" - : (decl_context == PARM - ? "storage class specified for parameter `%s'" - : "storage class specified for typename")), - name); - specbits &= ~ ((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER) - | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC) - | (1 << (int) RID_EXTERN)); - } - } - else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag) - { - /* `extern' with initialization is invalid if not at top level. */ - if (current_binding_level == global_binding_level) - warning ("`%s' initialized and declared `extern'", name); - else - error ("`%s' has both `extern' and initializer", name); - } - else if (specbits & 1 << (int) RID_EXTERN && funcdef_flag - && current_binding_level != global_binding_level) - error ("nested function `%s' declared `extern'", name); - else if (current_binding_level == global_binding_level - && specbits & (1 << (int) RID_AUTO)) - error ("top-level declaration of `%s' specifies `auto'", name); - else if ((specbits & 1 << (int) RID_ITERATOR) - && TREE_CODE (declarator) != IDENTIFIER_NODE) - { - error ("iterator `%s' has derived type", name); - type = error_mark_node; - } - else if ((specbits & 1 << (int) RID_ITERATOR) - && TREE_CODE (type) != INTEGER_TYPE) - { - error ("iterator `%s' has noninteger type", name); - type = error_mark_node; - } - } - - /* 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 absolute declarator). */ - - while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE) - { - if (type == error_mark_node) - { - declarator = TREE_OPERAND (declarator, 0); - continue; - } - - /* 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. - - 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 (TREE_CODE (declarator) == ARRAY_REF) - { - register tree itype = NULL_TREE; - register tree size = TREE_OPERAND (declarator, 1); - /* An uninitialized decl with `extern' is a reference. */ - int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN)); - /* The index is a signed object `sizetype' bits wide. */ - tree index_type = signed_type (sizetype); - - declarator = TREE_OPERAND (declarator, 0); - - /* Check for some types that there cannot be arrays of. */ - - if (TYPE_MAIN_VARIANT (type) == void_type_node) - { - error ("declaration of `%s' as array of voids", name); - type = error_mark_node; - } - - if (TREE_CODE (type) == FUNCTION_TYPE) - { - error ("declaration of `%s' as array of functions", name); - type = error_mark_node; - } - - if (size == error_mark_node) - type = error_mark_node; - - if (type == error_mark_node) - continue; - - /* If this is a block level extern, it must live past the end - of the function so that we can check it against other extern - declarations (IDENTIFIER_LIMBO_VALUE). */ - if (extern_ref && allocation_temporary_p ()) - end_temporary_allocation (); - - /* If size was specified, set ITYPE to a range-type for that size. - Otherwise, ITYPE remains null. finish_decl may figure it out - from an initial value. */ - - if (size) - { - /* 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) - { - error ("size of array `%s' has non-integer type", name); - size = integer_one_node; - } - - if (pedantic && integer_zerop (size)) - pedwarn ("ANSI C forbids zero-size array `%s'", name); - - if (TREE_CODE (size) == INTEGER_CST) - { - constant_expression_warning (size); - if (tree_int_cst_sgn (size) < 0) - { - error ("size of array `%s' is negative", name); - size = integer_one_node; - } - } - else - { - /* Make sure the array size remains visibly nonconstant - even if it is (eg) a const variable with known value. */ - size_varies = 1; - - if (pedantic) - { - if (TREE_CONSTANT (size)) - pedwarn ("ANSI C forbids array `%s' whose size can't be evaluated", name); - else - pedwarn ("ANSI C forbids variable-size array `%s'", name); - } - } - - /* Convert size to index_type, so that if it is a variable - the computations will be done in the proper mode. */ - itype = fold (build (MINUS_EXPR, index_type, - convert (index_type, size), - convert (index_type, size_one_node))); - - /* If that overflowed, the array is too big. - ??? While a size of INT_MAX+1 technically shouldn't cause - an overflow (because we subtract 1), the overflow is recorded - during the conversion to index_type, before the subtraction. - Handling this case seems like an unnecessary complication. */ - if (TREE_OVERFLOW (itype)) - { - error ("size of array `%s' is too large", name); - type = error_mark_node; - continue; - } - - if (size_varies) - itype = variable_size (itype); - itype = build_index_type (itype); - } - -#if 0 /* This had bad results for pointers to arrays, as in - union incomplete (*foo)[4]; */ - /* Complain about arrays of incomplete types, except in typedefs. */ - - if (TYPE_SIZE (type) == 0 - /* Avoid multiple warnings for nested array types. */ - && TREE_CODE (type) != ARRAY_TYPE - && !(specbits & (1 << (int) RID_TYPEDEF)) - && !C_TYPE_BEING_DEFINED (type)) - warning ("array type has incomplete element type"); -#endif - -#if 0 /* We shouldn't have a function type here at all! - Functions aren't allowed as array elements. */ - if (pedantic && TREE_CODE (type) == FUNCTION_TYPE - && (constp || volatilep)) - pedwarn ("ANSI C forbids const or volatile function types"); -#endif - - /* Build the array type itself, then merge any constancy or - volatility into the target type. We must do it in this order - to ensure that the TYPE_MAIN_VARIANT field of the array type - is set correctly. */ - - type = build_array_type (type, itype); - if (type_quals) - type = c_build_qualified_type (type, type_quals); - -#if 0 /* don't clear these; leave them set so that the array type - or the variable is itself const or volatile. */ - type_quals = TYPE_UNQUALIFIED; -#endif - - if (size_varies) - C_TYPE_VARIABLE_SIZE (type) = 1; - } - else if (TREE_CODE (declarator) == CALL_EXPR) - { - int extern_ref = (!(specbits & (1 << (int) RID_AUTO)) - || current_binding_level == global_binding_level); - tree arg_types; - - /* Declaring a function type. - Make sure we have a valid type for the function to return. */ - if (type == error_mark_node) - continue; - - size_varies = 0; - - /* Warn about some types functions can't return. */ - - if (TREE_CODE (type) == FUNCTION_TYPE) - { - error ("`%s' declared as function returning a function", name); - type = integer_type_node; - } - if (TREE_CODE (type) == ARRAY_TYPE) - { - error ("`%s' declared as function returning an array", name); - type = integer_type_node; - } - -#ifndef TRADITIONAL_RETURN_FLOAT - /* Traditionally, declaring return type float means double. */ - - if (flag_traditional && TYPE_MAIN_VARIANT (type) == float_type_node) - type = double_type_node; -#endif /* TRADITIONAL_RETURN_FLOAT */ - - /* If this is a block level extern, it must live past the end - of the function so that we can check it against other extern - declarations (IDENTIFIER_LIMBO_VALUE). */ - if (extern_ref && allocation_temporary_p ()) - end_temporary_allocation (); - - /* Construct the function type and go to the next - inner layer of declarator. */ - - arg_types = grokparms (TREE_OPERAND (declarator, 1), - funcdef_flag - /* Say it's a definition - only for the CALL_EXPR - closest to the identifier. */ - && TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE); -#if 0 /* This seems to be false. We turn off temporary allocation - above in this function if -traditional. - And this code caused inconsistent results with prototypes: - callers would ignore them, and pass arguments wrong. */ - - /* Omit the arg types if -traditional, since the arg types - and the list links might not be permanent. */ - type = build_function_type (type, - flag_traditional - ? NULL_TREE : arg_types); -#endif - /* Type qualifiers before the return type of the function - qualify the return type, not the function type. */ - if (type_quals) - type = c_build_qualified_type (type, type_quals); - type_quals = TYPE_UNQUALIFIED; - - type = build_function_type (type, arg_types); - declarator = TREE_OPERAND (declarator, 0); - - /* Set the TYPE_CONTEXTs for each tagged type which is local to - the formal parameter list of this FUNCTION_TYPE to point to - the FUNCTION_TYPE node itself. */ - - { - register tree link; - - for (link = last_function_parm_tags; - link; - link = TREE_CHAIN (link)) - TYPE_CONTEXT (TREE_VALUE (link)) = type; - } - } - else if (TREE_CODE (declarator) == INDIRECT_REF) - { - /* Merge any constancy or volatility into the target type - for the pointer. */ - - if (pedantic && TREE_CODE (type) == FUNCTION_TYPE - && type_quals) - pedwarn ("ANSI C forbids qualified function types"); - if (type_quals) - type = c_build_qualified_type (type, type_quals); - type_quals = TYPE_UNQUALIFIED; - size_varies = 0; - - type = build_pointer_type (type); - - /* Process a list of type modifier keywords - (such as const or volatile) that were given inside the `*'. */ - - if (TREE_TYPE (declarator)) - { - register tree typemodlist; - int erred = 0; - - constp = 0; - volatilep = 0; - restrictp = 0; - for (typemodlist = TREE_TYPE (declarator); typemodlist; - typemodlist = TREE_CHAIN (typemodlist)) - { - tree qualifier = TREE_VALUE (typemodlist); - - if (qualifier == ridpointers[(int) RID_CONST]) - constp++; - else if (qualifier == ridpointers[(int) RID_VOLATILE]) - volatilep++; - else if (qualifier == ridpointers[(int) RID_RESTRICT]) - restrictp++; - else if (!erred) - { - erred = 1; - error ("invalid type modifier within pointer declarator"); - } - } - if (constp > 1) - pedwarn ("duplicate `const'"); - if (volatilep > 1) - pedwarn ("duplicate `volatile'"); - if (restrictp > 1) - pedwarn ("duplicate `restrict'"); - - type_quals = ((constp ? TYPE_QUAL_CONST : 0) - | (restrictp ? TYPE_QUAL_RESTRICT : 0) - | (volatilep ? TYPE_QUAL_VOLATILE : 0)); - } - - declarator = TREE_OPERAND (declarator, 0); - } - else - abort (); - - } - - /* Now TYPE has the actual type. */ - - /* Did array size calculations overflow? */ - - if (TREE_CODE (type) == ARRAY_TYPE - && TYPE_SIZE (type) - && TREE_OVERFLOW (TYPE_SIZE (type))) - error ("size of array `%s' is too large", name); - - /* If this is declaring a typedef name, return a TYPE_DECL. */ - - if (specbits & (1 << (int) RID_TYPEDEF)) - { - tree decl; - /* Note that the grammar rejects storage classes - in typenames, fields or parameters */ - if (pedantic && TREE_CODE (type) == FUNCTION_TYPE - && type_quals) - pedwarn ("ANSI C forbids qualified function types"); - if (type_quals) - type = c_build_qualified_type (type, type_quals); - decl = build_decl (TYPE_DECL, declarator, type); - if ((specbits & (1 << (int) RID_SIGNED)) - || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))) - C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1; - pop_obstacks (); - return decl; - } - - /* Detect the case of an array type of unspecified size - which came, as such, direct from a typedef name. - We must copy the type, so that each identifier gets - a distinct type, so that each identifier's size can be - controlled separately by its own initializer. */ - - if (type != 0 && typedef_type != 0 - && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type) - && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0) - { - type = build_array_type (TREE_TYPE (type), 0); - if (size_varies) - C_TYPE_VARIABLE_SIZE (type) = 1; - } - - /* If this is a type name (such as, in a cast or sizeof), - compute the type and return it now. */ - - if (decl_context == TYPENAME) - { - /* Note that the grammar rejects storage classes - in typenames, fields or parameters */ - if (pedantic && TREE_CODE (type) == FUNCTION_TYPE - && type_quals) - pedwarn ("ANSI C forbids const or volatile function types"); - if (type_quals) - type = c_build_qualified_type (type, type_quals); - pop_obstacks (); - return type; - } - - /* Aside from typedefs and type names (handle above), - `void' at top level (not within pointer) - is allowed only in public variables. - We don't complain about parms either, but that is because - a better error message can be made later. */ - - if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM - && ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE) - && ((specbits & (1 << (int) RID_EXTERN)) - || (current_binding_level == global_binding_level - && !(specbits - & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER))))))) - { - error ("variable or field `%s' declared void", name); - type = integer_type_node; - } - - /* Now create the decl, which may be a VAR_DECL, a PARM_DECL - or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */ - - { - register tree decl; - - if (decl_context == PARM) - { - tree type_as_written = type; - tree main_type; - - /* A parameter declared as an array of T is really a pointer to T. - One declared as a function is really a pointer to a function. */ - - if (TREE_CODE (type) == ARRAY_TYPE) - { - /* Transfer const-ness of array into that of type pointed to. */ - type = TREE_TYPE (type); - if (type_quals) - type = c_build_qualified_type (type, type_quals); - type = build_pointer_type (type); - type_quals = TYPE_UNQUALIFIED; - size_varies = 0; - } - else if (TREE_CODE (type) == FUNCTION_TYPE) - { - if (pedantic && type_quals) - pedwarn ("ANSI C forbids qualified function types"); - if (type_quals) - type = c_build_qualified_type (type, type_quals); - type = build_pointer_type (type); - type_quals = TYPE_UNQUALIFIED; - } - - decl = build_decl (PARM_DECL, declarator, type); - if (size_varies) - C_DECL_VARIABLE_SIZE (decl) = 1; - - /* Compute the type actually passed in the parmlist, - for the case where there is no prototype. - (For example, shorts and chars are passed as ints.) - When there is a prototype, this is overridden later. */ - - DECL_ARG_TYPE (decl) = type; - main_type = (type == error_mark_node - ? error_mark_node - : TYPE_MAIN_VARIANT (type)); - if (main_type == float_type_node) - DECL_ARG_TYPE (decl) = double_type_node; - /* Don't use TYPE_PRECISION to decide whether to promote, - because we should convert short if it's the same size as int, - but we should not convert long if it's the same size as int. */ - else if (TREE_CODE (main_type) != ERROR_MARK - && C_PROMOTING_INTEGER_TYPE_P (main_type)) - { - if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node) - && TREE_UNSIGNED (type)) - DECL_ARG_TYPE (decl) = unsigned_type_node; - else - DECL_ARG_TYPE (decl) = integer_type_node; - } - - DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written; - } - else if (decl_context == FIELD) - { - /* Structure field. It may not be a function. */ - - if (TREE_CODE (type) == FUNCTION_TYPE) - { - error ("field `%s' declared as a function", name); - type = build_pointer_type (type); - } - else if (TREE_CODE (type) != ERROR_MARK && TYPE_SIZE (type) == 0) - { - error ("field `%s' has incomplete type", name); - type = error_mark_node; - } - /* Move type qualifiers down to element of an array. */ - if (TREE_CODE (type) == ARRAY_TYPE && type_quals) - { - type = build_array_type (c_build_qualified_type (TREE_TYPE (type), - type_quals), - TYPE_DOMAIN (type)); -#if 0 /* Leave the field const or volatile as well. */ - type_quals = TYPE_UNQUALIFIED; -#endif - } - decl = build_decl (FIELD_DECL, declarator, type); - if (size_varies) - C_DECL_VARIABLE_SIZE (decl) = 1; - } - else if (TREE_CODE (type) == FUNCTION_TYPE) - { - /* Every function declaration is "external" - except for those which are inside a function body - in which `auto' is used. - That is a case not specified by ANSI C, - and we use it for forward declarations for nested functions. */ - int extern_ref = (!(specbits & (1 << (int) RID_AUTO)) - || current_binding_level == global_binding_level); - - if (specbits & (1 << (int) RID_AUTO) - && (pedantic || current_binding_level == global_binding_level)) - pedwarn ("invalid storage class for function `%s'", name); - if (specbits & (1 << (int) RID_REGISTER)) - error ("invalid storage class for function `%s'", name); - /* Function declaration not at top level. - Storage classes other than `extern' are not allowed - and `extern' makes no difference. */ - if (current_binding_level != global_binding_level - && (specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_INLINE))) - && pedantic) - pedwarn ("invalid storage class for function `%s'", name); - - /* If this is a block level extern, it must live past the end - of the function so that we can check it against other - extern declarations (IDENTIFIER_LIMBO_VALUE). */ - if (extern_ref && allocation_temporary_p ()) - end_temporary_allocation (); - - decl = build_decl (FUNCTION_DECL, declarator, type); - decl = build_decl_attribute_variant (decl, decl_machine_attr); - - if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl)) - pedwarn ("ANSI C forbids qualified function types"); - - if (pedantic - && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node - && TYPE_QUALS (TREE_TYPE (TREE_TYPE (decl))) - && ! DECL_IN_SYSTEM_HEADER (decl)) - pedwarn ("ANSI C forbids qualified void function return type"); - - /* GNU C interprets a `volatile void' return type to indicate - that the function does not return. */ - if ((type_quals & TYPE_QUAL_VOLATILE) - && TREE_TYPE (TREE_TYPE (decl)) != void_type_node) - warning ("`noreturn' function returns non-void value"); - - if (extern_ref) - DECL_EXTERNAL (decl) = 1; - /* Record absence of global scope for `static' or `auto'. */ - TREE_PUBLIC (decl) - = !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO))); - - /* Record presence of `inline', if it is reasonable. */ - if (inlinep) - { - if (! strcmp (IDENTIFIER_POINTER (declarator), "main")) - warning ("cannot inline function `main'"); - else - /* Assume that otherwise the function can be inlined. */ - DECL_INLINE (decl) = 1; - - if (specbits & (1 << (int) RID_EXTERN)) - current_extern_inline = 1; - } - } - else - { - /* It's a variable. */ - /* An uninitialized decl with `extern' is a reference. */ - int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN)); - - /* Move type qualifiers down to element of an array. */ - if (TREE_CODE (type) == ARRAY_TYPE && type_quals) - { - type = build_array_type (c_build_qualified_type (TREE_TYPE (type), - type_quals), - TYPE_DOMAIN (type)); -#if 0 /* Leave the variable const or volatile as well. */ - type_quals = TYPE_UNQUALIFIED; -#endif - } - - /* If this is a block level extern, it must live past the end - of the function so that we can check it against other - extern declarations (IDENTIFIER_LIMBO_VALUE). */ - if (extern_ref && allocation_temporary_p ()) - end_temporary_allocation (); - - decl = build_decl (VAR_DECL, declarator, type); - if (size_varies) - C_DECL_VARIABLE_SIZE (decl) = 1; - - if (inlinep) - pedwarn_with_decl (decl, "variable `%s' declared `inline'"); - - DECL_EXTERNAL (decl) = extern_ref; - /* At top level, the presence of a `static' or `register' storage - class specifier, or the absence of all storage class specifiers - makes this declaration a definition (perhaps tentative). Also, - the absence of both `static' and `register' makes it public. */ - if (current_binding_level == global_binding_level) - { - TREE_PUBLIC (decl) - = !(specbits - & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER))); - TREE_STATIC (decl) = ! DECL_EXTERNAL (decl); - } - /* Not at top level, only `static' makes a static definition. */ - else - { - TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0; - TREE_PUBLIC (decl) = DECL_EXTERNAL (decl); - } - - if (specbits & 1 << (int) RID_ITERATOR) - ITERATOR_P (decl) = 1; - } - - /* Record `register' declaration for warnings on & - and in case doing stupid register allocation. */ - - if (specbits & (1 << (int) RID_REGISTER)) - DECL_REGISTER (decl) = 1; - - /* Record constancy and volatility. */ - c_apply_type_quals_to_decl (type_quals, decl); - - /* If a type has volatile components, it should be stored in memory. - Otherwise, the fact that those components are volatile - will be ignored, and would even crash the compiler. */ - if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl))) - mark_addressable (decl); - - pop_obstacks (); - - return decl; - } -} - -/* Decode the parameter-list info for a function type or function definition. - The argument is the value returned by `get_parm_info' (or made in parse.y - if there is an identifier list instead of a parameter decl list). - These two functions are separate because when a function returns - or receives functions then each is called multiple times but the order - of calls is different. The last call to `grokparms' is always the one - that contains the formal parameter names of a function definition. - - Store in `last_function_parms' a chain of the decls of parms. - Also store in `last_function_parm_tags' a chain of the struct, union, - and enum tags declared among the parms. - - Return a list of arg types to use in the FUNCTION_TYPE for this function. - - FUNCDEF_FLAG is nonzero for a function definition, 0 for - a mere declaration. A nonempty identifier-list gets an error message - when FUNCDEF_FLAG is zero. */ - -static tree -grokparms (parms_info, funcdef_flag) - tree parms_info; - int funcdef_flag; -{ - tree first_parm = TREE_CHAIN (parms_info); - - last_function_parms = TREE_PURPOSE (parms_info); - last_function_parm_tags = TREE_VALUE (parms_info); - - if (warn_strict_prototypes && first_parm == 0 && !funcdef_flag - && !in_system_header) - warning ("function declaration isn't a prototype"); - - if (first_parm != 0 - && TREE_CODE (TREE_VALUE (first_parm)) == IDENTIFIER_NODE) - { - if (! funcdef_flag) - pedwarn ("parameter names (without types) in function declaration"); - - last_function_parms = first_parm; - return 0; - } - else - { - tree parm; - tree typelt; - /* We no longer test FUNCDEF_FLAG. - If the arg types are incomplete in a declaration, - they must include undefined tags. - These tags can never be defined in the scope of the declaration, - so the types can never be completed, - and no call can be compiled successfully. */ -#if 0 - /* In a fcn definition, arg types must be complete. */ - if (funcdef_flag) -#endif - for (parm = last_function_parms, typelt = first_parm; - parm; - parm = TREE_CHAIN (parm)) - /* Skip over any enumeration constants declared here. */ - if (TREE_CODE (parm) == PARM_DECL) - { - /* Barf if the parameter itself has an incomplete type. */ - tree type = TREE_VALUE (typelt); - if (TYPE_SIZE (type) == 0) - { - if (funcdef_flag && DECL_NAME (parm) != 0) - error ("parameter `%s' has incomplete type", - IDENTIFIER_POINTER (DECL_NAME (parm))); - else - warning ("parameter has incomplete type"); - if (funcdef_flag) - { - TREE_VALUE (typelt) = error_mark_node; - TREE_TYPE (parm) = error_mark_node; - } - } -#if 0 /* This has been replaced by parm_tags_warning - which uses a more accurate criterion for what to warn about. */ - else - { - /* Now warn if is a pointer to an incomplete type. */ - while (TREE_CODE (type) == POINTER_TYPE - || TREE_CODE (type) == REFERENCE_TYPE) - type = TREE_TYPE (type); - type = TYPE_MAIN_VARIANT (type); - if (TYPE_SIZE (type) == 0) - { - if (DECL_NAME (parm) != 0) - warning ("parameter `%s' points to incomplete type", - IDENTIFIER_POINTER (DECL_NAME (parm))); - else - warning ("parameter points to incomplete type"); - } - } -#endif - typelt = TREE_CHAIN (typelt); - } - - /* Allocate the list of types the way we allocate a type. */ - if (first_parm && ! TREE_PERMANENT (first_parm)) - { - /* Construct a copy of the list of types - on the saveable obstack. */ - tree result = NULL; - for (typelt = first_parm; typelt; typelt = TREE_CHAIN (typelt)) - result = saveable_tree_cons (NULL_TREE, TREE_VALUE (typelt), - result); - return nreverse (result); - } - else - /* The list we have is permanent already. */ - return first_parm; - } -} - - -/* Return a tree_list node with info on a parameter list just parsed. - The TREE_PURPOSE is a chain of decls of those parms. - The TREE_VALUE is a list of structure, union and enum tags defined. - The TREE_CHAIN is a list of argument types to go in the FUNCTION_TYPE. - This tree_list node is later fed to `grokparms'. - - VOID_AT_END nonzero means append `void' to the end of the type-list. - Zero means the parmlist ended with an ellipsis so don't append `void'. */ - -tree -get_parm_info (void_at_end) - int void_at_end; -{ - register tree decl, t; - register tree types = 0; - int erred = 0; - tree tags = gettags (); - tree parms = getdecls (); - tree new_parms = 0; - tree order = current_binding_level->parm_order; - - /* Just `void' (and no ellipsis) is special. There are really no parms. */ - if (void_at_end && parms != 0 - && TREE_CHAIN (parms) == 0 - && TYPE_MAIN_VARIANT (TREE_TYPE (parms)) == void_type_node - && DECL_NAME (parms) == 0) - { - parms = NULL_TREE; - storedecls (NULL_TREE); - return saveable_tree_cons (NULL_TREE, NULL_TREE, - saveable_tree_cons (NULL_TREE, void_type_node, NULL_TREE)); - } - - /* Extract enumerator values and other non-parms declared with the parms. - Likewise any forward parm decls that didn't have real parm decls. */ - for (decl = parms; decl; ) - { - tree next = TREE_CHAIN (decl); - - if (TREE_CODE (decl) != PARM_DECL) - { - TREE_CHAIN (decl) = new_parms; - new_parms = decl; - } - else if (TREE_ASM_WRITTEN (decl)) - { - error_with_decl (decl, "parameter `%s' has just a forward declaration"); - TREE_CHAIN (decl) = new_parms; - new_parms = decl; - } - decl = next; - } - - /* Put the parm decls back in the order they were in in the parm list. */ - for (t = order; t; t = TREE_CHAIN (t)) - { - if (TREE_CHAIN (t)) - TREE_CHAIN (TREE_VALUE (t)) = TREE_VALUE (TREE_CHAIN (t)); - else - TREE_CHAIN (TREE_VALUE (t)) = 0; - } - - new_parms = chainon (order ? nreverse (TREE_VALUE (order)) : 0, - new_parms); - - /* Store the parmlist in the binding level since the old one - is no longer a valid list. (We have changed the chain pointers.) */ - storedecls (new_parms); - - for (decl = new_parms; decl; decl = TREE_CHAIN (decl)) - /* There may also be declarations for enumerators if an enumeration - type is declared among the parms. Ignore them here. */ - if (TREE_CODE (decl) == PARM_DECL) - { - /* Since there is a prototype, - args are passed in their declared types. */ - tree type = TREE_TYPE (decl); - DECL_ARG_TYPE (decl) = type; -#ifdef PROMOTE_PROTOTYPES - if ((TREE_CODE (type) == INTEGER_TYPE - || TREE_CODE (type) == ENUMERAL_TYPE) - && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) - DECL_ARG_TYPE (decl) = integer_type_node; -#endif - - types = saveable_tree_cons (NULL_TREE, TREE_TYPE (decl), types); - if (TYPE_MAIN_VARIANT (TREE_VALUE (types)) == void_type_node && ! erred - && DECL_NAME (decl) == 0) - { - error ("`void' in parameter list must be the entire list"); - erred = 1; - } - } - - if (void_at_end) - return saveable_tree_cons (new_parms, tags, - nreverse (saveable_tree_cons (NULL_TREE, void_type_node, types))); - - return saveable_tree_cons (new_parms, tags, nreverse (types)); -} - -/* At end of parameter list, warn about any struct, union or enum tags - defined within. Do so because these types cannot ever become complete. */ - -void -parmlist_tags_warning () -{ - tree elt; - static int already; - - for (elt = current_binding_level->tags; elt; elt = TREE_CHAIN (elt)) - { - enum tree_code code = TREE_CODE (TREE_VALUE (elt)); - /* An anonymous union parm type is meaningful as a GNU extension. - So don't warn for that. */ - if (code == UNION_TYPE && TREE_PURPOSE (elt) == 0 && !pedantic) - continue; - if (TREE_PURPOSE (elt) != 0) - warning ("`%s %s' declared inside parameter list", - (code == RECORD_TYPE ? "struct" - : code == UNION_TYPE ? "union" - : "enum"), - IDENTIFIER_POINTER (TREE_PURPOSE (elt))); - else - warning ("anonymous %s declared inside parameter list", - (code == RECORD_TYPE ? "struct" - : code == UNION_TYPE ? "union" - : "enum")); - - if (! already) - { - warning ("its scope is only this definition or declaration, which is probably not what you want."); - already = 1; - } - } -} - -/* Get the struct, enum or union (CODE says which) with tag NAME. - Define the tag as a forward-reference if it is not defined. */ - -tree -xref_tag (code, name) - enum tree_code code; - tree name; -{ - int temporary = allocation_temporary_p (); - - /* If a cross reference is requested, look up the type - 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) - return ref; - - push_obstacks_nochange (); - - if (current_binding_level == global_binding_level && temporary) - end_temporary_allocation (); - - /* If no such tag is yet defined, create a forward-reference node - and record it as the "definition". - When a real declaration of this type is found, - the forward-reference will be altered into a real type. */ - - ref = make_node (code); - if (code == ENUMERAL_TYPE) - { - /* (In ANSI, Enums can be referred to only if already defined.) */ - if (pedantic) - pedwarn ("ANSI C forbids forward references to `enum' types"); - /* Give the type a default layout like unsigned int - to avoid crashing if it does not get defined. */ - TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node); - TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node); - TREE_UNSIGNED (ref) = 1; - TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node); - TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node); - TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node); - } - - pushtag (name, ref); - - pop_obstacks (); - - return ref; -} - -/* Make sure that the tag NAME is defined *in the current binding level* - at least as a forward reference. - CODE says which kind of tag NAME ought to be. - - We also do a push_obstacks_nochange - whose matching pop is in finish_struct. */ - -tree -start_struct (code, name) - enum tree_code code; - tree name; -{ - /* If there is already a tag defined at this binding level - (as a forward reference), just return it. */ - - register tree ref = 0; - - push_obstacks_nochange (); - if (current_binding_level == global_binding_level) - end_temporary_allocation (); - - if (name != 0) - ref = lookup_tag (code, name, current_binding_level, 1); - if (ref && TREE_CODE (ref) == code) - { - C_TYPE_BEING_DEFINED (ref) = 1; - TYPE_PACKED (ref) = flag_pack_struct; - if (TYPE_FIELDS (ref)) - error ((code == UNION_TYPE ? "redefinition of `union %s'" - : "redefinition of `struct %s'"), - IDENTIFIER_POINTER (name)); - - return ref; - } - - /* Otherwise create a forward-reference just so the tag is in scope. */ - - ref = make_node (code); - pushtag (name, ref); - C_TYPE_BEING_DEFINED (ref) = 1; - TYPE_PACKED (ref) = flag_pack_struct; - return ref; -} - -/* Process the specs, declarator (NULL if omitted) 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. - - This is done during the parsing of the struct declaration. - The FIELD_DECL nodes are chained together and the lot of them - are ultimately passed to `build_struct' to make the RECORD_TYPE node. */ - -tree -grokfield (filename, line, declarator, declspecs, width) - const char *filename ATTRIBUTE_UNUSED; - int line ATTRIBUTE_UNUSED; - tree declarator, declspecs, width; -{ - tree value; - - /* The corresponding pop_obstacks is in finish_decl. */ - push_obstacks_nochange (); - - value = grokdeclarator (declarator, declspecs, width ? BITFIELD : FIELD, 0); - - finish_decl (value, NULL_TREE, NULL_TREE); - DECL_INITIAL (value) = width; - - maybe_objc_check_decl (value); - return value; -} - -/* Function to help qsort sort FIELD_DECLs by name order. */ - -static int -field_decl_cmp (xp, yp) - const GENERIC_PTR xp; - const GENERIC_PTR yp; -{ - tree *x = (tree *)xp, *y = (tree *)yp; - - if (DECL_NAME (*x) == DECL_NAME (*y)) - return 0; - if (DECL_NAME (*x) == NULL) - return -1; - if (DECL_NAME (*y) == NULL) - return 1; - if (DECL_NAME (*x) < DECL_NAME (*y)) - return -1; - return 1; -} - -/* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T. - FIELDLIST is a chain of FIELD_DECL nodes for the fields. - ATTRIBUTES are attributes to be applied to the structure. - - We also do a pop_obstacks to match the push in start_struct. */ - -tree -finish_struct (t, fieldlist, attributes) - tree t; - tree fieldlist; - tree attributes; -{ - register tree x; - int old_momentary; - int toplevel = global_binding_level == current_binding_level; - - /* If this type was previously laid out as a forward reference, - make sure we lay it out again. */ - - TYPE_SIZE (t) = 0; - - decl_attributes (t, attributes, NULL_TREE); - - /* Nameless union parm types are useful as GCC extension. */ - if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic) - /* Otherwise, warn about any struct or union def. in parmlist. */ - if (in_parm_level_p ()) - { - if (pedantic) - pedwarn ((TREE_CODE (t) == UNION_TYPE ? "union defined inside parms" - : "structure defined inside parms")); - else if (! flag_traditional) - warning ((TREE_CODE (t) == UNION_TYPE ? "union defined inside parms" - : "structure defined inside parms")); - } - - old_momentary = suspend_momentary (); - - if (pedantic) - { - for (x = fieldlist; x; x = TREE_CHAIN (x)) - if (DECL_NAME (x) != 0) - break; - - if (x == 0) - pedwarn ((fieldlist - ? "%s has no named members" - : "%s has no members"), - TREE_CODE (t) == UNION_TYPE ? "union" : "struct"); - } - - /* Install struct as DECL_CONTEXT of each field decl. - Also process specified field sizes. - Set DECL_FIELD_SIZE to the specified size, or 0 if none specified. - The specified size is found in the DECL_INITIAL. - Store 0 there, except for ": 0" fields (so we can find them - and delete them, below). */ - - for (x = fieldlist; x; x = TREE_CHAIN (x)) - { - DECL_CONTEXT (x) = t; - DECL_PACKED (x) |= TYPE_PACKED (t); - DECL_FIELD_SIZE (x) = 0; - - /* If any field is const, the structure type is pseudo-const. */ - if (TREE_READONLY (x)) - C_TYPE_FIELDS_READONLY (t) = 1; - else - { - /* A field that is pseudo-const makes the structure likewise. */ - tree t1 = TREE_TYPE (x); - while (TREE_CODE (t1) == ARRAY_TYPE) - t1 = TREE_TYPE (t1); - if ((TREE_CODE (t1) == RECORD_TYPE || TREE_CODE (t1) == UNION_TYPE) - && C_TYPE_FIELDS_READONLY (t1)) - C_TYPE_FIELDS_READONLY (t) = 1; - } - - /* Any field that is volatile means variables of this type must be - treated in some ways as volatile. */ - if (TREE_THIS_VOLATILE (x)) - C_TYPE_FIELDS_VOLATILE (t) = 1; - - /* Any field of nominal variable size implies structure is too. */ - if (C_DECL_VARIABLE_SIZE (x)) - C_TYPE_VARIABLE_SIZE (t) = 1; - - /* Detect invalid nested redefinition. */ - if (TREE_TYPE (x) == t) - error ("nested redefinition of `%s'", - IDENTIFIER_POINTER (TYPE_NAME (t))); - - /* Detect invalid bit-field size. */ - if (DECL_INITIAL (x)) - STRIP_NOPS (DECL_INITIAL (x)); - if (DECL_INITIAL (x)) - { - if (TREE_CODE (DECL_INITIAL (x)) == INTEGER_CST) - constant_expression_warning (DECL_INITIAL (x)); - else - { - error_with_decl (x, "bit-field `%s' width not an integer constant"); - DECL_INITIAL (x) = NULL; - } - } - - /* Detect invalid bit-field type. */ - if (DECL_INITIAL (x) - && TREE_CODE (TREE_TYPE (x)) != INTEGER_TYPE - && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE) - { - error_with_decl (x, "bit-field `%s' has invalid type"); - DECL_INITIAL (x) = NULL; - } - if (DECL_INITIAL (x) && pedantic - && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != integer_type_node - && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != unsigned_type_node - /* Accept an enum that's equivalent to int or unsigned int. */ - && !(TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE - && (TYPE_PRECISION (TREE_TYPE (x)) - == TYPE_PRECISION (integer_type_node)))) - pedwarn_with_decl (x, "bit-field `%s' type invalid in ANSI C"); - - /* Detect and ignore out of range field width. */ - if (DECL_INITIAL (x)) - { - unsigned HOST_WIDE_INT width = TREE_INT_CST_LOW (DECL_INITIAL (x)); - - if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0) - { - DECL_INITIAL (x) = NULL; - error_with_decl (x, "negative width in bit-field `%s'"); - } - else if (TREE_INT_CST_HIGH (DECL_INITIAL (x)) != 0 - || width > TYPE_PRECISION (TREE_TYPE (x))) - { - DECL_INITIAL (x) = NULL; - pedwarn_with_decl (x, "width of `%s' exceeds its type"); - } - else if (width == 0 && DECL_NAME (x) != 0) - { - error_with_decl (x, "zero width for bit-field `%s'"); - DECL_INITIAL (x) = NULL; - } - } - - /* Process valid field width. */ - if (DECL_INITIAL (x)) - { - register int width = TREE_INT_CST_LOW (DECL_INITIAL (x)); - - if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE - && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)), - TREE_UNSIGNED (TREE_TYPE (x))) - || width < min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)), - TREE_UNSIGNED (TREE_TYPE (x))))) - warning_with_decl (x, "`%s' is narrower than values of its type"); - - DECL_FIELD_SIZE (x) = width; - DECL_BIT_FIELD (x) = DECL_C_BIT_FIELD (x) = 1; - DECL_INITIAL (x) = NULL; - - if (width == 0) - { - /* field size 0 => force desired amount of alignment. */ -#ifdef EMPTY_FIELD_BOUNDARY - DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY); -#endif -#ifdef PCC_BITFIELD_TYPE_MATTERS - if (PCC_BITFIELD_TYPE_MATTERS) - DECL_ALIGN (x) = MAX (DECL_ALIGN (x), - TYPE_ALIGN (TREE_TYPE (x))); -#endif - } - } - else if (TREE_TYPE (x) != error_mark_node) - { - unsigned int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT - : TYPE_ALIGN (TREE_TYPE (x))); - /* Non-bit-fields are aligned for their type, except packed - fields which require only BITS_PER_UNIT alignment. */ - DECL_ALIGN (x) = MAX (DECL_ALIGN (x), min_align); - } - } - - /* Now DECL_INITIAL is null on all members. */ - - /* Delete all duplicate fields from the fieldlist */ - for (x = fieldlist; x && TREE_CHAIN (x);) - /* Anonymous fields aren't duplicates. */ - if (DECL_NAME (TREE_CHAIN (x)) == 0) - x = TREE_CHAIN (x); - else - { - register tree y = fieldlist; - - while (1) - { - if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x))) - break; - if (y == x) - break; - y = TREE_CHAIN (y); - } - if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x))) - { - error_with_decl (TREE_CHAIN (x), "duplicate member `%s'"); - TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x)); - } - else x = TREE_CHAIN (x); - } - - /* Now we have the nearly final fieldlist. Record it, - then lay out the structure or union (including the fields). */ - - TYPE_FIELDS (t) = fieldlist; - - layout_type (t); - - /* Delete all zero-width bit-fields from the front of the fieldlist */ - while (fieldlist - && DECL_INITIAL (fieldlist)) - fieldlist = TREE_CHAIN (fieldlist); - /* Delete all such members from the rest of the fieldlist */ - for (x = fieldlist; x;) - { - if (TREE_CHAIN (x) && DECL_INITIAL (TREE_CHAIN (x))) - TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x)); - else x = TREE_CHAIN (x); - } - - /* Now we have the truly final field list. - Store it in this type and in the variants. */ - - TYPE_FIELDS (t) = fieldlist; - - /* If there are lots of fields, sort so we can look through them fast. - We arbitrarily consider 16 or more elts to be "a lot". */ - { - int len = 0; - - for (x = fieldlist; x; x = TREE_CHAIN (x)) - { - if (len > 15) - break; - len += 1; - } - if (len > 15) - { - tree *field_array; - char *space; - - len += list_length (x); - /* Use the same allocation policy here that make_node uses, to - ensure that this lives as long as the rest of the struct decl. - All decls in an inline function need to be saved. */ - if (allocation_temporary_p ()) - space = savealloc (sizeof (struct lang_type) + len * sizeof (tree)); - else - space = oballoc (sizeof (struct lang_type) + len * sizeof (tree)); - - TYPE_LANG_SPECIFIC (t) = (struct lang_type *) space; - TYPE_LANG_SPECIFIC (t)->len = len; - - field_array = &TYPE_LANG_SPECIFIC (t)->elts[0]; - len = 0; - for (x = fieldlist; x; x = TREE_CHAIN (x)) - field_array[len++] = x; - - qsort (field_array, len, sizeof (tree), field_decl_cmp); - } - } - - for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x)) - { - TYPE_FIELDS (x) = TYPE_FIELDS (t); - TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t); - TYPE_ALIGN (x) = TYPE_ALIGN (t); - } - - /* If this was supposed to be a transparent union, but we can't - make it one, warn and turn off the flag. */ - if (TREE_CODE (t) == UNION_TYPE - && TYPE_TRANSPARENT_UNION (t) - && TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t))) - { - TYPE_TRANSPARENT_UNION (t) = 0; - warning ("union cannot be made transparent"); - } - - /* If this structure or union completes the type of any previous - variable declaration, lay it out and output its rtl. */ - - if (current_binding_level->n_incomplete != 0) - { - tree decl; - for (decl = current_binding_level->names; decl; decl = TREE_CHAIN (decl)) - { - if (TREE_TYPE (decl) == t - && TREE_CODE (decl) != TYPE_DECL) - { - layout_decl (decl, 0); - /* This is a no-op in c-lang.c or something real in objc-actions.c. */ - maybe_objc_check_decl (decl); - rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0); - if (! toplevel) - expand_decl (decl); - --current_binding_level->n_incomplete; - } - else if (TYPE_SIZE (TREE_TYPE (decl)) == 0 - && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) - { - tree element = TREE_TYPE (decl); - while (TREE_CODE (element) == ARRAY_TYPE) - element = TREE_TYPE (element); - if (element == t) - layout_array_type (TREE_TYPE (decl)); - } - } - } - - resume_momentary (old_momentary); - - /* Finish debugging output for this type. */ - rest_of_type_compilation (t, toplevel); - - /* The matching push is in start_struct. */ - pop_obstacks (); - - return t; -} - -/* Lay out the type T, and its element type, and so on. */ - -static void -layout_array_type (t) - tree t; -{ - if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) - layout_array_type (TREE_TYPE (t)); - layout_type (t); -} - -/* Begin compiling the definition of an enumeration type. - NAME is its name (or null if anonymous). - Returns the type object, as yet incomplete. - Also records info about it so that build_enumerator - may be used to declare the individual values as they are read. */ - -tree -start_enum (name) - tree name; -{ - register tree enumtype = 0; - - /* If this is the real definition for a previous forward reference, - fill in the contents in the same object that used to be the - forward reference. */ - - if (name != 0) - enumtype = lookup_tag (ENUMERAL_TYPE, name, current_binding_level, 1); - - /* The corresponding pop_obstacks is in finish_enum. */ - push_obstacks_nochange (); - /* If these symbols and types are global, make them permanent. */ - if (current_binding_level == global_binding_level) - end_temporary_allocation (); - - if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE) - { - enumtype = make_node (ENUMERAL_TYPE); - pushtag (name, enumtype); - } - - C_TYPE_BEING_DEFINED (enumtype) = 1; - - if (TYPE_VALUES (enumtype) != 0) - { - /* This enum is a named one that has been declared already. */ - error ("redeclaration of `enum %s'", IDENTIFIER_POINTER (name)); - - /* Completely replace its old definition. - The old enumerators remain defined, however. */ - TYPE_VALUES (enumtype) = 0; - } - - enum_next_value = integer_zero_node; - enum_overflow = 0; - - if (flag_short_enums) - TYPE_PACKED (enumtype) = 1; - - return enumtype; -} - -/* After processing and defining all the values of an enumeration type, - install their decls in the enumeration type and finish it off. - ENUMTYPE is the type object, VALUES a list of decl-value pairs, - and ATTRIBUTES are the specified attributes. - Returns ENUMTYPE. */ - -tree -finish_enum (enumtype, values, attributes) - tree enumtype; - tree values; - tree attributes; -{ - register tree pair, tem; - tree minnode = 0, maxnode = 0; - int lowprec, highprec, precision; - int toplevel = global_binding_level == current_binding_level; - - if (in_parm_level_p ()) - warning ("enum defined inside parms"); - - decl_attributes (enumtype, attributes, NULL_TREE); - - /* Calculate the maximum value of any enumerator in this type. */ - - if (values == error_mark_node) - minnode = maxnode = integer_zero_node; - else - for (pair = values; pair; pair = TREE_CHAIN (pair)) - { - tree value = TREE_VALUE (pair); - if (pair == values) - minnode = maxnode = TREE_VALUE (pair); - else - { - if (tree_int_cst_lt (maxnode, value)) - maxnode = value; - if (tree_int_cst_lt (value, minnode)) - minnode = value; - } - } - - TYPE_MIN_VALUE (enumtype) = minnode; - TYPE_MAX_VALUE (enumtype) = maxnode; - - /* An enum can have some negative values; then it is signed. */ - TREE_UNSIGNED (enumtype) = tree_int_cst_sgn (minnode) >= 0; - - /* Determine the precision this type needs. */ - - lowprec = min_precision (minnode, TREE_UNSIGNED (enumtype)); - highprec = min_precision (maxnode, TREE_UNSIGNED (enumtype)); - precision = MAX (lowprec, highprec); - - if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node)) - { - tree narrowest = type_for_size (precision, 1); - if (narrowest == 0) - { - warning ("enumeration values exceed range of largest integer"); - narrowest = long_long_integer_type_node; - } - - TYPE_PRECISION (enumtype) = TYPE_PRECISION (narrowest); - } - else - TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node); - - TYPE_SIZE (enumtype) = 0; - layout_type (enumtype); - - if (values != error_mark_node) - { - /* Change the type of the enumerators to be the enum type. - Formerly this was done only for enums that fit in an int, - but the comment said it was done only for enums wider than int. - It seems necessary to do this for wide enums, - and best not to change what's done for ordinary narrower ones. */ - for (pair = values; pair; pair = TREE_CHAIN (pair)) - { - TREE_TYPE (TREE_PURPOSE (pair)) = enumtype; - DECL_SIZE (TREE_PURPOSE (pair)) = TYPE_SIZE (enumtype); - if (TREE_CODE (TREE_PURPOSE (pair)) != FUNCTION_DECL) - DECL_ALIGN (TREE_PURPOSE (pair)) = TYPE_ALIGN (enumtype); - } - - /* Replace the decl nodes in VALUES with their names. */ - for (pair = values; pair; pair = TREE_CHAIN (pair)) - TREE_PURPOSE (pair) = DECL_NAME (TREE_PURPOSE (pair)); - - TYPE_VALUES (enumtype) = values; - } - - /* Fix up all variant types of this enum type. */ - for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem)) - { - TYPE_VALUES (tem) = TYPE_VALUES (enumtype); - TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype); - TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype); - TYPE_SIZE (tem) = TYPE_SIZE (enumtype); - TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype); - TYPE_MODE (tem) = TYPE_MODE (enumtype); - TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype); - TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype); - TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype); - } - - /* Finish debugging output for this type. */ - rest_of_type_compilation (enumtype, toplevel); - - /* This matches a push in start_enum. */ - pop_obstacks (); - - return enumtype; -} - -/* Build and install a CONST_DECL for one value of the - current enumeration type (one that was begun with start_enum). - Return a tree-list containing the CONST_DECL and its value. - Assignment of sequential values by default is handled here. */ - -tree -build_enumerator (name, value) - tree name, value; -{ - register tree decl, type; - - /* Validate and default VALUE. */ - - /* Remove no-op casts from the value. */ - if (value) - STRIP_TYPE_NOPS (value); - - if (value != 0) - { - if (TREE_CODE (value) == INTEGER_CST) - { - value = default_conversion (value); - constant_expression_warning (value); - } - else - { - error ("enumerator value for `%s' not integer constant", - IDENTIFIER_POINTER (name)); - value = 0; - } - } - - /* Default based on previous value. */ - /* It should no longer be possible to have NON_LVALUE_EXPR - in the default. */ - if (value == 0) - { - value = enum_next_value; - if (enum_overflow) - error ("overflow in enumeration values"); - } - - if (pedantic && ! int_fits_type_p (value, integer_type_node)) - { - pedwarn ("ANSI C restricts enumerator values to range of `int'"); - value = integer_zero_node; - } - - /* Set basis for default for next value. */ - enum_next_value = build_binary_op (PLUS_EXPR, value, integer_one_node, 0); - enum_overflow = tree_int_cst_lt (enum_next_value, value); - - /* Now create a declaration for the enum value name. */ - - type = TREE_TYPE (value); - type = type_for_size (MAX (TYPE_PRECISION (type), - TYPE_PRECISION (integer_type_node)), - ((flag_traditional - || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node)) - && TREE_UNSIGNED (type))); - - decl = build_decl (CONST_DECL, name, type); - DECL_INITIAL (decl) = value; - TREE_TYPE (value) = type; - pushdecl (decl); - - return saveable_tree_cons (decl, value, NULL_TREE); -} - -/* Create the FUNCTION_DECL for a function definition. - DECLSPECS, DECLARATOR, PREFIX_ATTRIBUTES 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. - - 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. - - NESTED is nonzero for a function nested within another function. */ - -int -start_function (declspecs, declarator, prefix_attributes, attributes, nested) - tree declarator, declspecs, prefix_attributes, attributes; - int nested; -{ - tree decl1, old_decl; - tree restype; - int old_immediate_size_expand = immediate_size_expand; - - current_function_returns_value = 0; /* Assume, until we see it does. */ - current_function_returns_null = 0; - warn_about_return_type = 0; - current_extern_inline = 0; - c_function_varargs = 0; - named_labels = 0; - shadowed_labels = 0; - - /* Don't expand any sizes in the return type of the function. */ - immediate_size_expand = 0; - - decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1); - - /* If the declarator is not suitable for a function definition, - cause a syntax error. */ - if (decl1 == 0) - { - immediate_size_expand = old_immediate_size_expand; - return 0; - } - - decl_attributes (decl1, prefix_attributes, attributes); - - announce_function (decl1); - - if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl1))) == 0) - { - error ("return-type is an incomplete type"); - /* Make it return void instead. */ - TREE_TYPE (decl1) - = build_function_type (void_type_node, - TYPE_ARG_TYPES (TREE_TYPE (decl1))); - } - - if (warn_about_return_type) - warning ("return-type defaults to `int'"); - - /* Save the parm names or decls from this function's declarator - where store_parm_decls will find them. */ - current_function_parms = last_function_parms; - current_function_parm_tags = last_function_parm_tags; - - /* Make the init_value nonzero so pushdecl knows this is not tentative. - error_mark_node is replaced below (in poplevel) with the BLOCK. */ - DECL_INITIAL (decl1) = error_mark_node; - - /* If this definition isn't a prototype and we had a prototype declaration - before, copy the arg type info from that prototype. - But not if what we had before was a builtin function. */ - old_decl = lookup_name_current_level (DECL_NAME (decl1)); - if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE - && !DECL_BUILT_IN (old_decl) - && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1))) - == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (old_decl)))) - && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0) - { - TREE_TYPE (decl1) = TREE_TYPE (old_decl); - current_function_prototype_file = DECL_SOURCE_FILE (old_decl); - current_function_prototype_line = DECL_SOURCE_LINE (old_decl); - } - - /* If there is no explicit declaration, look for any out-of-scope implicit - declarations. */ - if (old_decl == 0) - old_decl = IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)); - - /* Optionally warn of old-fashioned def with no previous prototype. */ - if (warn_strict_prototypes - && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0 - && !(old_decl != 0 && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0)) - warning ("function declaration isn't a prototype"); - /* Optionally warn of any global def with no previous prototype. */ - else if (warn_missing_prototypes - && TREE_PUBLIC (decl1) - && !(old_decl != 0 && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0) - && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1)))) - warning_with_decl (decl1, "no previous prototype for `%s'"); - /* Optionally warn of any def with no previous prototype - if the function has already been used. */ - else if (warn_missing_prototypes - && old_decl != 0 && TREE_USED (old_decl) - && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) == 0) - warning_with_decl (decl1, - "`%s' was used with no prototype before its definition"); - /* Optionally warn of any global def with no previous declaration. */ - else if (warn_missing_declarations - && TREE_PUBLIC (decl1) - && old_decl == 0 - && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1)))) - warning_with_decl (decl1, "no previous declaration for `%s'"); - /* Optionally warn of any def with no previous declaration - if the function has already been used. */ - else if (warn_missing_declarations - && old_decl != 0 && TREE_USED (old_decl) - && old_decl == IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1))) - warning_with_decl (decl1, - "`%s' was used with no declaration before its definition"); - - /* This is a definition, not a reference. - So normally clear DECL_EXTERNAL. - However, `extern inline' acts like a declaration - 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; - - /* A nested function is not global. */ - if (current_function_decl != 0) - TREE_PUBLIC (decl1) = 0; - - /* Warn for unlikely, improbable, or stupid declarations of `main'. */ - if (warn_main > 0 - && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))) == 0) - { - tree args; - int argct = 0; - - if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1))) - != integer_type_node) - pedwarn_with_decl (decl1, "return type of `%s' is not `int'"); - - for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args; - args = TREE_CHAIN (args)) - { - tree type = args ? TREE_VALUE (args) : 0; - - if (type == void_type_node) - break; - - ++argct; - switch (argct) - { - case 1: - if (TYPE_MAIN_VARIANT (type) != integer_type_node) - pedwarn_with_decl (decl1, - "first argument of `%s' should be `int'"); - break; - - case 2: - if (TREE_CODE (type) != POINTER_TYPE - || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE - || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) - != char_type_node)) - pedwarn_with_decl (decl1, - "second argument of `%s' should be `char **'"); - break; - - case 3: - if (TREE_CODE (type) != POINTER_TYPE - || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE - || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) - != char_type_node)) - pedwarn_with_decl (decl1, - "third argument of `%s' should probably be `char **'"); - break; - } - } - - /* It is intentional that this message does not mention the third - argument, which is warned for only pedantically, because it's - blessed by mention in an appendix of the standard. */ - if (argct > 0 && (argct < 2 || argct > 3)) - pedwarn_with_decl (decl1, "`%s' takes only zero or two arguments"); - - if (argct == 3 && pedantic) - pedwarn_with_decl (decl1, "third argument of `%s' is deprecated"); - - if (! TREE_PUBLIC (decl1)) - pedwarn_with_decl (decl1, "`%s' is normally a non-static function"); - } - - /* Record the decl so that the function name is defined. - If we already have a decl for this name, and it is a FUNCTION_DECL, - use the old decl. */ - - current_function_decl = pushdecl (decl1); - - pushlevel (0); - declare_parm_level (1); - current_binding_level->subblocks_tag_transparent = 1; - - make_function_rtl (current_function_decl); - - restype = TREE_TYPE (TREE_TYPE (current_function_decl)); - /* Promote the value to int before returning it. */ - if (C_PROMOTING_INTEGER_TYPE_P (restype)) - { - /* It retains unsignedness if traditional - or if not really getting wider. */ - if (TREE_UNSIGNED (restype) - && (flag_traditional - || (TYPE_PRECISION (restype) - == TYPE_PRECISION (integer_type_node)))) - restype = unsigned_type_node; - else - restype = integer_type_node; - } - DECL_RESULT (current_function_decl) - = build_decl (RESULT_DECL, NULL_TREE, restype); - - if (!nested) - /* Allocate further tree nodes temporarily during compilation - of this function only. */ - temporary_allocation (); - - /* If this fcn was already referenced via a block-scope `extern' decl - (or an implicit decl), propagate certain information about the usage. */ - if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl))) - TREE_ADDRESSABLE (current_function_decl) = 1; - - immediate_size_expand = old_immediate_size_expand; - - return 1; -} - -/* Record that this function is going to be a varargs function. - This is called before store_parm_decls, which is too early - to call mark_varargs directly. */ - -void -c_mark_varargs () -{ - c_function_varargs = 1; -} - -/* Store the parameter declarations into the current function declaration. - This is called after parsing the parameter declarations, before - digesting the body of the function. - - For an old-style definition, modify the function's type - to specify at least the number of arguments. */ - -void -store_parm_decls () -{ - register tree fndecl = current_function_decl; - register tree parm; - - /* This is either a chain of PARM_DECLs (if a prototype was used) - or a list of IDENTIFIER_NODEs (for an old-fashioned C definition). */ - tree specparms = current_function_parms; - - /* This is a list of types declared among parms in a prototype. */ - tree parmtags = current_function_parm_tags; - - /* This is a chain of PARM_DECLs from old-style parm declarations. */ - register tree parmdecls = getdecls (); - - /* This is a chain of any other decls that came in among the parm - declarations. If a parm is declared with enum {foo, bar} x; - then CONST_DECLs for foo and bar are put here. */ - tree nonparms = 0; - - /* Nonzero if this definition is written with a prototype. */ - int prototype = 0; - - if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST) - { - /* This case is when the function was defined with an ANSI prototype. - The parms already have decls, so we need not do anything here - except record them as in effect - and complain if any redundant old-style parm decls were written. */ - - register tree next; - tree others = 0; - - prototype = 1; - - if (parmdecls != 0) - { - tree decl, link; - - error_with_decl (fndecl, - "parm types given both in parmlist and separately"); - /* Get rid of the erroneous decls; don't keep them on - the list of parms, since they might not be PARM_DECLs. */ - for (decl = current_binding_level->names; - decl; decl = TREE_CHAIN (decl)) - if (DECL_NAME (decl)) - IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)) = 0; - for (link = current_binding_level->shadowed; - link; link = TREE_CHAIN (link)) - IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); - current_binding_level->names = 0; - current_binding_level->shadowed = 0; - } - - specparms = nreverse (specparms); - for (parm = specparms; parm; parm = next) - { - next = TREE_CHAIN (parm); - if (TREE_CODE (parm) == PARM_DECL) - { - if (DECL_NAME (parm) == 0) - error_with_decl (parm, "parameter name omitted"); - else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node) - { - error_with_decl (parm, "parameter `%s' declared void"); - /* Change the type to error_mark_node so this parameter - will be ignored by assign_parms. */ - TREE_TYPE (parm) = error_mark_node; - } - pushdecl (parm); - } - else - { - /* If we find an enum constant or a type tag, - put it aside for the moment. */ - TREE_CHAIN (parm) = 0; - others = chainon (others, parm); - } - } - - /* Get the decls in their original chain order - and record in the function. */ - DECL_ARGUMENTS (fndecl) = getdecls (); - -#if 0 - /* If this function takes a variable number of arguments, - add a phony parameter to the end of the parm list, - to represent the position of the first unnamed argument. */ - if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))) - != void_type_node) - { - tree dummy = build_decl (PARM_DECL, NULL_TREE, void_type_node); - /* Let's hope the address of the unnamed parm - won't depend on its type. */ - TREE_TYPE (dummy) = integer_type_node; - DECL_ARG_TYPE (dummy) = integer_type_node; - DECL_ARGUMENTS (fndecl) - = chainon (DECL_ARGUMENTS (fndecl), dummy); - } -#endif - - /* Now pushdecl the enum constants. */ - for (parm = others; parm; parm = next) - { - next = TREE_CHAIN (parm); - if (DECL_NAME (parm) == 0) - ; - else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node) - ; - else if (TREE_CODE (parm) != PARM_DECL) - pushdecl (parm); - } - - storetags (chainon (parmtags, gettags ())); - } - else - { - /* SPECPARMS is an identifier list--a chain of TREE_LIST nodes - each with a parm name as the TREE_VALUE. - - PARMDECLS is a chain of declarations for parameters. - Warning! It can also contain CONST_DECLs which are not parameters - but are names of enumerators of any enum types - declared among the parameters. - - First match each formal parameter name with its declaration. - Associate decls with the names and store the decls - into the TREE_PURPOSE slots. */ - - for (parm = parmdecls; parm; parm = TREE_CHAIN (parm)) - DECL_RESULT (parm) = 0; - - for (parm = specparms; parm; parm = TREE_CHAIN (parm)) - { - register tree tail, found = NULL; - - if (TREE_VALUE (parm) == 0) - { - error_with_decl (fndecl, "parameter name missing from parameter list"); - TREE_PURPOSE (parm) = 0; - continue; - } - - /* See if any of the parmdecls specifies this parm by name. - Ignore any enumerator decls. */ - for (tail = parmdecls; tail; tail = TREE_CHAIN (tail)) - if (DECL_NAME (tail) == TREE_VALUE (parm) - && TREE_CODE (tail) == PARM_DECL) - { - found = tail; - break; - } - - /* If declaration already marked, we have a duplicate name. - Complain, and don't use this decl twice. */ - if (found && DECL_RESULT (found) != 0) - { - error_with_decl (found, "multiple parameters named `%s'"); - found = 0; - } - - /* If the declaration says "void", complain and ignore it. */ - if (found && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == void_type_node) - { - 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); - if (extra_warnings) - warning_with_decl (found, "type of `%s' defaults to `int'"); - pushdecl (found); - } - - TREE_PURPOSE (parm) = found; - - /* Mark this decl as "already found" -- see test, above. - It is safe to use DECL_RESULT for this - since it is not used in PARM_DECLs or CONST_DECLs. */ - DECL_RESULT (found) = error_mark_node; - } - - /* Put anything which is on the parmdecls chain and which is - not a PARM_DECL onto the list NONPARMS. (The types of - non-parm things which might appear on the list include - enumerators and NULL-named TYPE_DECL nodes.) Complain about - any actual PARM_DECLs not matched with any names. */ - - nonparms = 0; - for (parm = parmdecls; parm; ) - { - tree next = TREE_CHAIN (parm); - TREE_CHAIN (parm) = 0; - - if (TREE_CODE (parm) != PARM_DECL) - nonparms = chainon (nonparms, parm); - else - { - /* Complain about args with incomplete types. */ - if (TYPE_SIZE (TREE_TYPE (parm)) == 0) - { - error_with_decl (parm, "parameter `%s' has incomplete type"); - TREE_TYPE (parm) = error_mark_node; - } - - if (DECL_RESULT (parm) == 0) - { - 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. */ - /* Store that chain in the function decl, replacing the list of names. */ - parm = specparms; - DECL_ARGUMENTS (fndecl) = 0; - { - register tree last; - for (last = 0; parm; parm = TREE_CHAIN (parm)) - if (TREE_PURPOSE (parm)) - { - if (last == 0) - DECL_ARGUMENTS (fndecl) = TREE_PURPOSE (parm); - else - TREE_CHAIN (last) = TREE_PURPOSE (parm); - last = TREE_PURPOSE (parm); - TREE_CHAIN (last) = 0; - } - } - - /* If there was a previous prototype, - set the DECL_ARG_TYPE of each argument according to - the type previously specified, and report any mismatches. */ - - if (TYPE_ARG_TYPES (TREE_TYPE (fndecl))) - { - register tree type; - for (parm = DECL_ARGUMENTS (fndecl), - type = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); - parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type)) - != void_type_node)); - parm = TREE_CHAIN (parm), type = TREE_CHAIN (type)) - { - if (parm == 0 || type == 0 - || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node) - { - error ("number of arguments doesn't match prototype"); - error_with_file_and_line (current_function_prototype_file, - current_function_prototype_line, - "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))) - { - if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) - == TYPE_MAIN_VARIANT (TREE_VALUE (type))) - { - /* Adjust argument to match prototype. E.g. a previous - `int foo(float);' prototype causes - `int foo(x) float x; {...}' to be treated like - `int foo(float x) {...}'. This is particularly - useful for argument types like uid_t. */ - DECL_ARG_TYPE (parm) = TREE_TYPE (parm); -#ifdef PROMOTE_PROTOTYPES - if ((TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE - || TREE_CODE (TREE_TYPE (parm)) == ENUMERAL_TYPE) - && TYPE_PRECISION (TREE_TYPE (parm)) - < TYPE_PRECISION (integer_type_node)) - DECL_ARG_TYPE (parm) = integer_type_node; -#endif - if (pedantic) - { - pedwarn ("promoted argument `%s' doesn't match prototype", - IDENTIFIER_POINTER (DECL_NAME (parm))); - warning_with_file_and_line - (current_function_prototype_file, - current_function_prototype_line, - "prototype declaration"); - } - } - /* If -traditional, allow `int' argument to match - `unsigned' prototype. */ - else if (! (flag_traditional - && TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == integer_type_node - && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node)) - { - error ("argument `%s' doesn't match prototype", - IDENTIFIER_POINTER (DECL_NAME (parm))); - error_with_file_and_line (current_function_prototype_file, - current_function_prototype_line, - "prototype declaration"); - } - } - } - TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = 0; - } - - /* Otherwise, create a prototype that would match. */ - - else - { - tree actual = 0, last = 0, type; - - for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm)) - { - type = perm_tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), - NULL_TREE); - if (last) - TREE_CHAIN (last) = type; - else - actual = type; - last = type; - } - type = perm_tree_cons (NULL_TREE, void_type_node, NULL_TREE); - if (last) - TREE_CHAIN (last) = type; - else - actual = type; - - /* We are going to assign a new value for the TYPE_ACTUAL_ARG_TYPES - of the type of this function, but we need to avoid having this - affect the types of other similarly-typed functions, so we must - first force the generation of an identical (but separate) type - node for the relevant function type. The new node we create - will be a variant of the main variant of the original function - type. */ - - TREE_TYPE (fndecl) = build_type_copy (TREE_TYPE (fndecl)); - - TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = actual; - } - - /* Now store the final chain of decls for the arguments - as the decl-chain of the current lexical scope. - Put the enumerators in as well, at the front so that - DECL_ARGUMENTS is not modified. */ - - storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl))); - } - - /* Make sure the binding level for the top of the function body - gets a BLOCK if there are any in the function. - Otherwise, the dbx output is wrong. */ - - keep_next_if_subblocks = 1; - - /* ??? This might be an improvement, - but needs to be thought about some more. */ -#if 0 - keep_next_level_flag = 1; -#endif - - /* Write a record describing this function definition to the prototypes - file (if requested). */ - - gen_aux_info_record (fndecl, 1, 0, prototype); - - /* Initialize the RTL code for the function. */ - - init_function_start (fndecl, input_filename, lineno); - - /* If this is a varargs function, inform function.c. */ - - if (c_function_varargs) - mark_varargs (); - - /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */ - - declare_function_name (); - - /* Set up parameters and prepare for return, for the function. */ - - expand_function_start (fndecl, 0); - - /* If this function is `main', emit a call to `__main' - to run global initializers, etc. */ - if (DECL_NAME (fndecl) - && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main") == 0 - && DECL_CONTEXT (fndecl) == NULL_TREE) - expand_main_function (); -} - -/* 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_RESULT (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_RESULT (found) != 0) - { - error_with_decl (found, "multiple parameters named `%s'"); - found = 0; - } - - /* If the declaration says "void", complain and ignore it. */ - if (found && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == void_type_node) - { - 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" -- see test, above. - It is safe to use DECL_RESULT for this - since it is not used in PARM_DECLs or CONST_DECLs. */ - DECL_RESULT (found) = error_mark_node; - } - - /* 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 (TYPE_SIZE (TREE_TYPE (parm)) == 0) - { - error_with_decl (parm, "parameter `%s' has incomplete type"); - TREE_TYPE (parm) = error_mark_node; - } - - if (DECL_RESULT (parm) == 0) - { - 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 = saveable_tree_cons (NULL_TREE, TREE_TYPE (parm), types); - } - } - - if (void_at_end) - return saveable_tree_cons (parmdecls, nonparms, - nreverse (saveable_tree_cons (NULL_TREE, - void_type_node, - types))); - - return saveable_tree_cons (parmdecls, nonparms, nreverse (types)); -} - -/* Finish up a function declaration and compile that function - all the way to assembler language output. The free the storage - for the function definition. - - This is called after parsing the body of the function definition. - - NESTED is nonzero if the function being finished is nested in another. */ - -void -finish_function (nested) - int nested; -{ - register tree fndecl = current_function_decl; - -/* TREE_READONLY (fndecl) = 1; - This caused &foo to be of type ptr-to-const-function - which then got a warning when stored in a ptr-to-function variable. */ - - poplevel (1, 0, 1); - BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; - - /* Must mark the RESULT_DECL as being in this function. */ - - DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl; - - /* Obey `register' declarations if `setjmp' is called in this fn. */ - if (flag_traditional && current_function_calls_setjmp) - { - setjmp_protect (DECL_INITIAL (fndecl)); - setjmp_protect_args (); - } - - if (! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")) - { - if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) - != integer_type_node) - { - /* If warn_main is 1 (-Wmain) or 2 (-Wall), we have already warned. - If warn_main is -1 (-Wno-main) we don't want to be warned. */ - if (! warn_main) - pedwarn_with_decl (fndecl, "return type of `%s' is not `int'"); - } - else - { -#ifdef DEFAULT_MAIN_RETURN - /* Make it so that `main' always returns success by default. */ - DEFAULT_MAIN_RETURN; -#endif - } - } - - /* Generate rtl for function exit. */ - expand_function_end (input_filename, lineno, 0); - - /* So we can tell if jump_optimize sets it to 1. */ - can_reach_end = 0; - - /* Run the optimizers and output the assembler code for this function. */ - rest_of_compilation (fndecl); - - current_function_returns_null |= can_reach_end; - - if (warn_missing_noreturn - && !TREE_THIS_VOLATILE (fndecl) - && !current_function_returns_null - && !current_function_returns_value) - warning ("function might be possible candidate for attribute `noreturn'"); - - if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null) - warning ("`noreturn' function does return"); - else if (warn_return_type && can_reach_end - && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) != void_type_node) - /* If this function returns non-void and control can drop through, - complain. */ - warning ("control reaches end of non-void function"); - /* With just -W, complain only if function returns both with - and without a value. */ - else if (extra_warnings - && current_function_returns_value && current_function_returns_null) - warning ("this function may return with or without a value"); - - /* If requested, warn about function definitions where the function will - return a value (usually of some struct or union type) which itself will - take up a lot of stack space. */ - - if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl)) - { - register tree ret_type = TREE_TYPE (TREE_TYPE (fndecl)); - - if (ret_type) - { - register tree ret_type_size = TYPE_SIZE (ret_type); - - if (TREE_CODE (ret_type_size) == INTEGER_CST) - { - unsigned units - = TREE_INT_CST_LOW (ret_type_size) / BITS_PER_UNIT; - - if (units > larger_than_size) - warning_with_decl (fndecl, - "size of return value of `%s' is %u bytes", - units); - } - } - } - - /* Free all the tree nodes making up this function. */ - /* Switch back to allocating nodes permanently - until we start another function. */ - if (! nested) - permanent_allocation (1); - - if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested) - { - /* Stop pointing to the local nodes about to be freed. */ - /* But DECL_INITIAL must remain nonzero so we know this - was an actual function definition. */ - /* For a nested function, this is done in pop_c_function_context. */ - /* If rest_of_compilation set this to 0, leave it 0. */ - if (DECL_INITIAL (fndecl) != 0) - DECL_INITIAL (fndecl) = error_mark_node; - DECL_ARGUMENTS (fndecl) = 0; - } - - if (DECL_STATIC_CONSTRUCTOR (fndecl)) - { -#ifndef ASM_OUTPUT_CONSTRUCTOR - if (! flag_gnu_linker) - static_ctors = perm_tree_cons (NULL_TREE, fndecl, static_ctors); - else -#endif - assemble_constructor (IDENTIFIER_POINTER (DECL_NAME (fndecl))); - } - if (DECL_STATIC_DESTRUCTOR (fndecl)) - { -#ifndef ASM_OUTPUT_DESTRUCTOR - if (! flag_gnu_linker) - static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors); - else -#endif - assemble_destructor (IDENTIFIER_POINTER (DECL_NAME (fndecl))); - } - - if (! nested) - { - /* Let the error reporting routines know that we're outside a - function. For a nested function, this value is used in - pop_c_function_context and then reset via pop_function_context. */ - current_function_decl = NULL; - } -} - -/* 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. */ - -struct c_function -{ - struct c_function *next; - tree named_labels; - tree shadowed_labels; - int returns_value; - int returns_null; - int warn_about_return_type; - int extern_inline; - struct binding_level *binding_level; -}; - -struct c_function *c_function_chain; - -/* Save and reinitialize the variables - used during compilation of a C function. */ - -void -push_c_function_context () -{ - struct c_function *p - = (struct c_function *) xmalloc (sizeof (struct c_function)); - - if (pedantic) - pedwarn ("ANSI C forbids nested functions"); - - push_function_context (); - - p->next = c_function_chain; - c_function_chain = p; - - p->named_labels = named_labels; - p->shadowed_labels = shadowed_labels; - p->returns_value = current_function_returns_value; - p->returns_null = current_function_returns_null; - p->warn_about_return_type = warn_about_return_type; - p->extern_inline = current_extern_inline; - p->binding_level = current_binding_level; -} - -/* Restore the variables used during compilation of a C function. */ - -void -pop_c_function_context () -{ - struct c_function *p = c_function_chain; - tree link; - - /* Bring back all the labels that were shadowed. */ - for (link = shadowed_labels; link; link = TREE_CHAIN (link)) - if (DECL_NAME (TREE_VALUE (link)) != 0) - IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link))) - = TREE_VALUE (link); - - if (DECL_SAVED_INSNS (current_function_decl) == 0) - { - /* Stop pointing to the local nodes about to be freed. */ - /* But DECL_INITIAL must remain nonzero so we know this - was an actual function definition. */ - DECL_INITIAL (current_function_decl) = error_mark_node; - DECL_ARGUMENTS (current_function_decl) = 0; - } - - pop_function_context (); - - c_function_chain = p->next; - - named_labels = p->named_labels; - shadowed_labels = p->shadowed_labels; - current_function_returns_value = p->returns_value; - current_function_returns_null = p->returns_null; - warn_about_return_type = p->warn_about_return_type; - current_extern_inline = p->extern_inline; - current_binding_level = p->binding_level; - - free (p); -} - -/* integrate_decl_tree calls this function, but since we don't use the - DECL_LANG_SPECIFIC field, this is a no-op. */ - -void -copy_lang_decl (node) - tree node ATTRIBUTE_UNUSED; -{ -} |