#include "config.h"
#include "system.h"
#include "intl.h"
#include "tree.h"
#include "tree-inline.h"
#include "rtl.h"
#include "flags.h"
#include "function.h"
#include "output.h"
#include "expr.h"
#include "c-tree.h"
#include "c-lex.h"
#include "toplev.h"
#include "ggc.h"
#include "tm_p.h"
#include "cpplib.h"
#include "target.h"
#include "debug.h"
#include "timevar.h"
#include "c-common.h"
#include "c-pragma.h"
#include "genindex.h"
#ifdef ENABLE_DMP_TREE
#include "dmp-tree.h"
extern int c_dump_tree_p PARAMS ((FILE *, const char *, tree, int));
extern lang_dump_tree_p_t c_prev_lang_dump_tree_p;
#endif
#ifdef PFE
#include "pfe/pfe.h"
#include "pfe/pfe-header.h"
extern int flag_keep_static_consts;
#endif
enum decl_context
{ NORMAL,
FUNCDEF,
PARM,
FIELD,
BITFIELD,
TYPENAME};
tree pending_invalid_xref;
const char *pending_invalid_xref_file;
int pending_invalid_xref_line;
static tree enum_next_value;
static int enum_overflow;
static tree last_function_parms;
static tree last_function_parm_tags;
static tree current_function_parms;
static tree current_function_parm_tags;
static const char *current_function_prototype_file;
static int current_function_prototype_line;
static struct stmt_tree_s c_stmt_tree;
static tree c_scope_stmt_stack;
static tree named_labels;
static tree shadowed_labels;
static int c_function_varargs;
int current_function_returns_value;
int current_function_returns_null;
int current_function_returns_abnormally;
static int warn_about_return_type;
static int current_extern_inline;
struct binding_level
{
tree names;
tree tags;
tree shadowed;
tree blocks;
tree this_block;
struct binding_level *level_chain;
char parm_flag;
char tag_transparent;
char subblocks_tag_transparent;
char keep;
char keep_if_subblocks;
tree incomplete_list;
tree parm_order;
};
#define NULL_BINDING_LEVEL (struct binding_level *) NULL
static struct binding_level *current_binding_level;
static struct binding_level *free_binding_level;
static struct binding_level *global_binding_level;
static struct binding_level clear_binding_level
= {NULL, NULL, NULL, NULL, NULL, NULL_BINDING_LEVEL, 0, 0, 0, 0, 0, NULL,
NULL};
static int keep_next_level_flag;
static int keep_next_if_subblocks;
static struct binding_level *label_level_chain;
tree static_ctors, static_dtors;
static struct binding_level * make_binding_level PARAMS ((void));
static void mark_binding_level PARAMS ((void *));
static void clear_limbo_values PARAMS ((tree));
static int duplicate_decls PARAMS ((tree, tree, int));
static int redeclaration_error_message PARAMS ((tree, tree));
static void storedecls PARAMS ((tree));
static void storetags PARAMS ((tree));
static tree lookup_tag PARAMS ((enum tree_code, tree,
struct binding_level *, int));
static tree lookup_tag_reverse PARAMS ((tree));
static tree grokdeclarator PARAMS ((tree, tree, enum decl_context,
int));
static tree grokparms PARAMS ((tree, int));
static void layout_array_type PARAMS ((tree));
static tree c_make_fname_decl PARAMS ((tree, int));
static void c_expand_body PARAMS ((tree, int, int));
static void warn_if_shadowing PARAMS ((tree, tree));
int flag_cond_mismatch;
int flag_no_asm;
int flag_traditional;
int flag_isoc94 = 0;
int flag_isoc99 = 0;
int flag_hosted = 1;
int flag_noniso_default_format_attributes = 1;
int flag_allow_single_precision = 0;
int flag_signed_bitfields = 1;
int explicit_flag_signed_bitfields = 0;
int warn_implicit_int;
int warn_long_long = 1;
int mesg_implicit_function_declaration = -1;
int flag_const_strings;
int warn_cast_qual;
int warn_bad_function_cast;
int warn_missing_format_attribute;
int warn_traditional;
int warn_pointer_arith;
int warn_strict_prototypes;
int warn_missing_prototypes;
int warn_missing_declarations;
int warn_redundant_decls = 0;
int warn_nested_externs = 0;
int warn_char_subscripts = 0;
int warn_conversion;
int warn_parentheses;
int warn_missing_braces;
int warn_main;
int warn_unknown_pragmas = 0;
int warn_sign_compare = -1;
int warn_float_equal = 0;
int warn_multichar = 1;
int warn_altivec_long_deprecated = 1;
#ifndef WARN_FOUR_CHAR_CONSTANTS
#define WARN_FOUR_CHAR_CONSTANTS 1
#endif
int warn_four_char_constants = WARN_FOUR_CHAR_CONSTANTS;
#ifndef DOLLARS_IN_IDENTIFIERS
#define DOLLARS_IN_IDENTIFIERS 1
#endif
int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
enum deprecated_states {
DEPRECATED_NORMAL,
DEPRECATED_SUPPRESS
, DEPRECATED_UNAVAILABLE_SUPPRESS
};
static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
int
c_decode_option (argc, argv)
int argc ATTRIBUTE_UNUSED;
char **argv;
{
int strings_processed;
char *p = argv[0];
strings_processed = cpp_handle_option (parse_in, argc, argv, 0);
if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
{
warning ("-traditional is deprecated and may be removed");
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;
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))
{
const char *const argstart = &p[5];
if (!strcmp (argstart, "iso9899:1990")
|| !strcmp (argstart, "c89"))
{
iso_1990:
flag_isoc94 = 0;
iso_1994:
flag_traditional = 0;
flag_writable_strings = 0;
flag_no_asm = 1;
flag_no_nonansi_builtin = 1;
flag_noniso_default_format_attributes = 0;
flag_isoc99 = 0;
}
else if (!strcmp (argstart, "iso9899:199409"))
{
flag_isoc94 = 1;
goto iso_1994;
}
else if (!strcmp (argstart, "iso9899:199x")
|| !strcmp (argstart, "iso9899:1999")
|| !strcmp (argstart, "c9x")
|| !strcmp (argstart, "c99"))
{
flag_traditional = 0;
flag_writable_strings = 0;
flag_no_asm = 1;
flag_no_nonansi_builtin = 1;
flag_noniso_default_format_attributes = 0;
flag_isoc99 = 1;
flag_isoc94 = 1;
}
else if (!strcmp (argstart, "gnu89"))
{
flag_traditional = 0;
flag_writable_strings = 0;
flag_no_asm = 0;
flag_no_nonansi_builtin = 0;
flag_noniso_default_format_attributes = 1;
flag_isoc99 = 0;
flag_isoc94 = 0;
}
else if (!strcmp (argstart, "gnu9x") || !strcmp (argstart, "gnu99"))
{
flag_traditional = 0;
flag_writable_strings = 0;
flag_no_asm = 0;
flag_no_nonansi_builtin = 0;
flag_noniso_default_format_attributes = 1;
flag_isoc99 = 1;
flag_isoc94 = 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, "-fshort-wchar"))
flag_short_wchar = 1;
else if (!strcmp (p, "-fno-short-wchar"))
flag_short_wchar = 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, "-faltivec"))
flag_altivec = 1;
else if (!strcmp (p, "-fno-altivec"))
flag_altivec = 0;
else if (!strcmp (p, "-fconstant-cfstrings"))
flag_constant_cfstrings = 1;
else if (!strcmp (p, "-fno-constant-cfstrings"))
flag_constant_cfstrings = 0;
else if (!strcmp (p, "-fbuiltin"))
flag_no_builtin = 0;
else if (!strcmp (p, "-fno-builtin"))
flag_no_builtin = 1;
else if (!strncmp (p, "-fno-builtin-", strlen ("-fno-builtin-")))
disable_builtin_function (p + strlen ("-fno-builtin-"));
else if (p[0] == '-' && p[1] == 'f' && dump_switch_p (p + 2))
;
else if (!strcmp (p, "-ansi"))
goto iso_1990;
else if (!strcmp (p, "-Werror-implicit-function-declaration"))
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-double"))
warn_long_double = 1;
else if (!strcmp (p, "-Wno-long-double"))
warn_long_double = 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, "-Wno-missing-noreturn"))
warn_missing_noreturn = 0;
else if (!strcmp (p, "-Wmissing-format-attribute"))
warn_missing_format_attribute = 1;
else if (!strcmp (p, "-Wno-missing-format-attribute"))
warn_missing_format_attribute = 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 (!strncmp (p, "-Wformat=", 9))
set_Wformat (atoi (p + 9));
else if (!strcmp (p, "-Wformat"))
set_Wformat (1);
else if (!strcmp (p, "-Wno-format"))
set_Wformat (0);
else if (!strcmp (p, "-Wformat-y2k"))
warn_format_y2k = 1;
else if (!strcmp (p, "-Wno-format-y2k"))
warn_format_y2k = 0;
else if (!strcmp (p, "-Wformat-extra-args"))
warn_format_extra_args = 1;
else if (!strcmp (p, "-Wno-format-extra-args"))
warn_format_extra_args = 0;
else if (!strcmp (p, "-Wformat-nonliteral"))
warn_format_nonliteral = 1;
else if (!strcmp (p, "-Wno-format-nonliteral"))
warn_format_nonliteral = 0;
else if (!strcmp (p, "-Wformat-security"))
warn_format_security = 1;
else if (!strcmp (p, "-Wno-format-security"))
warn_format_security = 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, "-Wsequence-point"))
warn_sequence_point = 1;
else if (!strcmp (p, "-Wno-sequence-point"))
warn_sequence_point = 0;
else if (!strcmp (p, "-Wcomment"))
;
else if (!strcmp (p, "-Wno-comment"))
;
else if (!strcmp (p, "-Wcomments"))
;
else if (!strcmp (p, "-Wno-comments"))
;
else if (!strcmp (p, "-Wtrigraphs"))
;
else if (!strcmp (p, "-Wno-trigraphs"))
;
else if (!strcmp (p, "-Wundef"))
;
else if (!strcmp (p, "-Wno-undef"))
;
else if (!strcmp (p, "-Wimport"))
;
else if (!strcmp (p, "-Wno-import"))
;
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, "-Wfloat-equal"))
warn_float_equal = 1;
else if (!strcmp (p, "-Wno-float-equal"))
warn_float_equal = 0;
else if (!strcmp (p, "-Wmultichar"))
warn_multichar = 1;
else if (!strcmp (p, "-Wno-multichar"))
warn_multichar = 0;
else if (!strcmp (p, "-Wfour-char-constants"))
warn_four_char_constants = 1;
else if (!strcmp (p, "-Wno-four-char-constants"))
warn_four_char_constants = 0;
else if (!strcmp (p, "-Wdiv-by-zero"))
warn_div_by_zero = 1;
else if (!strcmp (p, "-Wno-div-by-zero"))
warn_div_by_zero = 0;
else if (!strcmp (p, "-Wunknown-pragmas"))
warn_unknown_pragmas = 2;
else if (!strcmp (p, "-Wno-unknown-pragmas"))
warn_unknown_pragmas = 0;
else if (!strcmp (p, "-Waltivec-long-deprecated"))
warn_altivec_long_deprecated = 1;
else if (!strcmp (p, "-Wno-altivec-long-deprecated"))
warn_altivec_long_deprecated = 0;
else if (!strcmp (p, "-Wall") || !strcmp (p, "-Wmost"))
{
if (warn_uninitialized != 1)
warn_uninitialized = 2;
warn_implicit_int = 1;
mesg_implicit_function_declaration = 1;
warn_return_type = 1;
set_Wunused (1);
warn_switch = 1;
set_Wformat (1);
warn_char_subscripts = 1;
warn_parentheses = 1;
warn_sequence_point = 1;
warn_missing_braces = 1;
warn_main = 2;
warn_unknown_pragmas = 1;
if (!strcmp (p, "-Wmost"))
{
warn_parentheses = 0;
}
}
else
return strings_processed;
return 1;
}
void
c_print_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);
if (C_IS_RESERVED_WORD (node))
{
tree rid = ridpointers[C_RID_CODE (node)];
indent_to (file, indent + 4);
fprintf (file, "rid ");
fprintf (file, HOST_PTR_PRINTF, (void *)rid);
fprintf (file, " \"%s\"", IDENTIFIER_POINTER (rid));
}
}
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
&& ! DECL_EXTERNAL (decl)
&& TYPE_DOMAIN (type) == 0)
{
warning_with_decl (decl, "array `%s' assumed to have one element");
complete_array_type (type, NULL_TREE, 1);
layout_decl (decl, 0);
}
}
}
static struct binding_level *
make_binding_level ()
{
return (struct binding_level *)
PFE_MALLOC (sizeof (struct binding_level), PFE_ALLOC_BINDING_LEVEL);
}
struct binding_level *
get_current_binding_level ()
{
return current_binding_level;
}
int
global_bindings_p ()
{
return current_binding_level == global_binding_level;
}
void
keep_next_level ()
{
keep_next_level_flag = 1;
}
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));
}
void
declare_parm_level (definition_flag)
int definition_flag ATTRIBUTE_UNUSED;
{
current_binding_level->parm_flag = 1;
}
int
in_parm_level_p ()
{
return current_binding_level->parm_flag;
}
void
pushlevel (tag_transparent)
int tag_transparent;
{
struct binding_level *newlevel = NULL_BINDING_LEVEL;
if (current_binding_level == global_binding_level)
{
named_labels = 0;
}
if (free_binding_level)
{
newlevel = free_binding_level;
free_binding_level = free_binding_level->level_chain;
}
else
{
newlevel = make_binding_level ();
}
*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;
}
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);
}
tree
poplevel (keep, reverse, functionbody)
int keep;
int reverse;
int functionbody;
{
tree link;
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;
#if 0
for (link = tags; link; link = TREE_CHAIN (link))
if (!COMPLETE_TYPE_P (TREE_VALUE (link)))
{
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
if (reverse)
current_binding_level->names
= decls = nreverse (current_binding_level->names);
else
decls = current_binding_level->names;
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 (DECL_ABSTRACT_ORIGIN (decl) != 0
&& DECL_ABSTRACT_ORIGIN (decl) != decl)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
}
warn_about_unused_variables (getdecls ());
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_SUBBLOCKS (block) = subblocks;
}
for (link = subblocks; link; link = TREE_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block;
for (link = decls; link; link = TREE_CHAIN (link))
{
if (DECL_NAME (link) != 0)
{
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;
}
}
for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
if (functionbody)
{
clear_limbo_values (block);
BLOCK_VARS (block) = 0;
for (link = named_labels; link; link = TREE_CHAIN (link))
{
tree label = TREE_VALUE (link);
if (DECL_INITIAL (label) == 0)
{
error_with_decl (label, "label `%s' used but not defined");
define_label (input_filename, lineno,
DECL_NAME (label));
}
else if (warn_unused_label && !TREE_USED (label))
warning_with_decl (label, "label `%s' defined but not used");
IDENTIFIER_LABEL_VALUE (DECL_NAME (label)) = 0;
TREE_CHAIN (label) = BLOCK_VARS (block);
BLOCK_VARS (block) = label;
}
}
{
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;
}
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);
}
else if (subblocks)
current_binding_level->blocks
= chainon (current_binding_level->blocks, subblocks);
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;
}
void
insert_block (block)
tree block;
{
TREE_USED (block) = 1;
current_binding_level->blocks
= chainon (current_binding_level->blocks, block);
}
void
set_block (block)
tree block;
{
current_binding_level->this_block = block;
current_binding_level->names = chainon (current_binding_level->names,
BLOCK_VARS (block));
current_binding_level->blocks = chainon (current_binding_level->blocks,
BLOCK_SUBBLOCKS (block));
}
void
push_label_level ()
{
struct binding_level *newlevel;
if (free_binding_level)
{
newlevel = free_binding_level;
free_binding_level = free_binding_level->level_chain;
}
else
{
newlevel = make_binding_level ();
}
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 ()
{
struct binding_level *level = label_level_chain;
tree link, prev;
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");
define_label (input_filename, lineno,
DECL_NAME (TREE_VALUE (link)));
}
else if (warn_unused_label && !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;
link = TREE_CHAIN (link);
if (prev)
TREE_CHAIN (prev) = link;
else
named_labels = link;
}
else
{
prev = link;
link = TREE_CHAIN (link);
}
}
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;
label_level_chain = label_level_chain->level_chain;
level->level_chain = free_binding_level;
free_binding_level = level;
}
void
pushtag (name, type)
tree name, type;
{
struct binding_level *b;
for (b = current_binding_level; b->tag_transparent; b = b->level_chain)
continue;
if (name)
{
if (TYPE_NAME (type) == 0)
TYPE_NAME (type) = name;
}
b->tags = tree_cons (name, type, b->tags);
TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type));
TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
}
static int
duplicate_decls (newdecl, olddecl, different_binding_level)
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 (DECL_P (olddecl))
{
if (TREE_CODE (newdecl) == FUNCTION_DECL
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)))
{
if (DECL_DECLARED_INLINE_P (newdecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
;
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
;
else if (DECL_DECLARED_INLINE_P (newdecl)
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
warning_with_decl (newdecl,
"function `%s' redeclared as inline");
warning_with_decl (olddecl,
"previous declaration of function `%s' with attribute noinline");
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
warning_with_decl (newdecl,
"function `%s' redeclared with attribute noinline");
warning_with_decl (olddecl,
"previous declaration of function `%s' was inline");
}
}
DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
}
if (TREE_CODE (newtype) == ERROR_MARK
|| TREE_CODE (oldtype) == ERROR_MARK)
types_match = 0;
if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& (DECL_BUILT_IN (olddecl)
|| DECL_BUILT_IN_NONANSI (olddecl)))
{
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'");
}
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;
}
if (types_match && TREE_CODE (newdecl) == PARM_DECL
&& TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
return 1;
if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL
&& IDENTIFIER_IMPLICIT_DECL (DECL_NAME (newdecl)) == olddecl
&& DECL_INITIAL (olddecl) == 0)
;
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_BUILT_IN (olddecl))
{
if (!TREE_PUBLIC (newdecl))
{
if (warn_shadow)
warning_with_decl (newdecl, "shadowing built-in function `%s'");
return 0;
}
else if (!types_match)
{
tree oldreturntype = TREE_TYPE (oldtype);
tree newreturntype = TREE_TYPE (newtype);
if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
{
tree trytype
= build_function_type (newreturntype,
TYPE_ARG_TYPES (oldtype));
trytype = build_type_attribute_variant (trytype,
TYPE_ATTRIBUTES (oldtype));
types_match = comptypes (newtype, trytype);
if (types_match)
oldtype = trytype;
}
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)))))
{
tree trytype
= build_function_type (TREE_TYPE (oldtype),
tree_cons (NULL_TREE,
TREE_VALUE (TYPE_ARG_TYPES (newtype)),
TREE_CHAIN (TYPE_ARG_TYPES (oldtype))));
trytype = build_type_attribute_variant (trytype,
TYPE_ATTRIBUTES (oldtype));
types_match = comptypes (newtype, trytype);
if (types_match)
oldtype = trytype;
}
if (! different_binding_level)
TREE_TYPE (olddecl) = oldtype;
}
else if (TYPE_ARG_TYPES (oldtype) == NULL
&& TYPE_ARG_TYPES (newtype) != NULL)
{
tree trytype
= build_function_type (TREE_TYPE (oldtype),
TYPE_ARG_TYPES (newtype));
trytype = build_type_attribute_variant (trytype,
TYPE_ATTRIBUTES (oldtype));
oldtype = trytype;
if (! different_binding_level)
TREE_TYPE (olddecl) = oldtype;
}
if (!types_match)
{
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)
{
if (!TREE_PUBLIC (newdecl))
{
return 0;
}
else if (!types_match)
{
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
}
}
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'");
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (oldtype))) == void_type_node)
TREE_TYPE (newdecl) = newtype = oldtype;
DECL_IN_SYSTEM_HEADER (newdecl) = 1;
}
else if (!types_match
&& ! (TREE_CODE (olddecl) == FUNCTION_DECL
&& ! pedantic
&& comptypes (TREE_TYPE (oldtype),
TREE_TYPE (newtype))
&& TYPE_ARG_TYPES (newtype) == 0))
{
error_with_decl (newdecl, "conflicting types for `%s'");
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)))
{
tree t = TYPE_ARG_TYPES (oldtype);
if (t == 0)
t = TYPE_ARG_TYPES (newtype);
for (; t; t = TREE_CHAIN (t))
{
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 (simple_type_promotes_to (type) != NULL_TREE)
{
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"));
return 0;
}
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)
{
tree type, parm;
int nargs;
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;
}
if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type))
&& (! (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;
}
}
}
else
{
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& DECL_DECLARED_INLINE_P (newdecl)
&& TREE_USED (olddecl))
warning_with_decl (newdecl,
"`%s' declared inline after being called");
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& DECL_DECLARED_INLINE_P (newdecl)
&& DECL_INITIAL (olddecl) != 0)
warning_with_decl (newdecl,
"`%s' declared inline after its definition");
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 && !in_system_header
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& !TREE_PUBLIC (olddecl)
&& TREE_PUBLIC (newdecl))
warning_with_decl (newdecl, "non-static declaration for `%s' follows static");
if (TREE_CODE (olddecl) != FUNCTION_DECL
&& !TREE_READONLY (olddecl)
&& TREE_READONLY (newdecl))
warning_with_decl (newdecl, "const declaration for `%s' follows non-const");
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");
}
}
if (errmsg == 0 && warn_redundant_decls && DECL_SOURCE_LINE (olddecl) != 0
&& !(TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0
&& DECL_INITIAL (olddecl) == 0)
&& !(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'");
}
if (types_match)
{
tree write_olddecl = different_binding_level ? newdecl : olddecl;
if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
{
if (different_binding_level)
{
if (TYPE_ARG_TYPES (oldtype) != 0
&& TYPE_ARG_TYPES (newtype) == 0)
TREE_TYPE (newdecl) = common_type (newtype, oldtype);
else
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);
}
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
{
DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (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);
DECL_USER_ALIGN (newdecl) |= DECL_ALIGN (olddecl);
}
}
COPY_DECL_RTL (olddecl, newdecl);
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& 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
&& errmsg == 0)
make_var_volatile (newdecl);
}
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);
}
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;
if (DECL_INITIAL (newdecl) == 0 && ! different_binding_level)
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
}
if (DECL_WEAK_IMPORT (olddecl) != DECL_WEAK_IMPORT (newdecl))
{
if (! DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
warning_with_decl (newdecl,
"inconsistent weak_import attribute with previous declaration of `%s'");
DECL_WEAK_IMPORT (newdecl) = 1;
}
}
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);
}
DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
if (! TREE_PUBLIC (olddecl))
TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
}
if (DECL_EXTERNAL (newdecl))
{
if (! different_binding_level)
{
TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
}
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 (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (new_is_definition && DECL_INITIAL (olddecl) && TREE_USED (olddecl))
{
(*debug_hooks->outlining_inline_function) (olddecl);
DECL_INLINE (newdecl) = 0;
DECL_UNINLINABLE (newdecl) = 1;
}
else
{
if (DECL_DECLARED_INLINE_P (newdecl)
|| DECL_DECLARED_INLINE_P (olddecl))
DECL_DECLARED_INLINE_P (newdecl) = 1;
DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
}
if (DECL_BUILT_IN (olddecl))
{
if (! types_match || new_is_definition)
{
if (! different_binding_level)
{
TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
}
}
else
{
DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
}
}
if (! new_is_definition)
{
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
if (! different_binding_level)
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
if (DECL_INLINE (olddecl) && ! DECL_UNINLINABLE (newdecl))
{
DECL_INLINE (newdecl) = 1;
DECL_ABSTRACT_ORIGIN (newdecl)
= (different_binding_level
? DECL_ORIGIN (olddecl)
: DECL_ABSTRACT_ORIGIN (olddecl));
}
}
else
{
if (DECL_DECLARED_INLINE_P (newdecl)
&& ! DECL_UNINLINABLE (newdecl))
DECL_INLINE (newdecl) = 1;
}
}
if (different_binding_level)
return 0;
{
unsigned olddecl_uid = DECL_UID (olddecl);
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl) - sizeof (struct tree_common));
DECL_UID (olddecl) = olddecl_uid;
}
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
return 1;
}
static void
warn_if_shadowing (x, oldlocal)
tree x, oldlocal;
{
tree name;
if (DECL_EXTERNAL (x))
return;
name = DECL_NAME (x);
if (oldlocal != 0
&& ! current_binding_level->parm_flag
&& current_binding_level->level_chain->parm_flag
&& 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));
}
else if (warn_shadow
&& DECL_SOURCE_LINE (x) != 0
&& ! DECL_FROM_INLINE (x))
{
if (TREE_CODE (x) == PARM_DECL
&& current_binding_level->level_chain->parm_flag)
;
else if (oldlocal)
{
if (TREE_CODE (oldlocal) == PARM_DECL)
shadow_warning ("a parameter", name, oldlocal);
else
shadow_warning ("a previous local", name, oldlocal);
}
else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
&& IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
shadow_warning ("a global declaration", name,
IDENTIFIER_GLOBAL_VALUE (name));
}
}
tree
pushdecl (x)
tree x;
{
tree t;
tree name = DECL_NAME (x);
struct binding_level *b = current_binding_level;
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
DECL_LANG_SPECIFIC (x) = (struct lang_decl *)
GGC_ALLOC_CLEARED (sizeof (struct lang_decl), PFE_ALLOC_GGC_LANG_DECL);
DECL_CONTEXT (x) = current_function_decl;
if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
&& DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
DECL_CONTEXT (x) = 0;
if (name)
{
int different_binding_level = 0;
if (warn_nested_externs
&& DECL_EXTERNAL (x)
&& b != global_binding_level
&& x != IDENTIFIER_IMPLICIT_DECL (name)
&& !DECL_IN_SYSTEM_HEADER (x))
warning ("nested extern declaration of `%s'",
IDENTIFIER_POINTER (name));
t = lookup_name_current_level (name);
if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional)
{
t = IDENTIFIER_GLOBAL_VALUE (name);
if (! t || TREE_CODE (t) == TYPE_DECL)
t = IDENTIFIER_LIMBO_VALUE (name);
different_binding_level = 1;
}
if (t != 0 && t == error_mark_node)
{
t = 0;
error_with_decl (x, "`%s' used prior to declaration");
}
if (! flag_traditional && TREE_PUBLIC (name)
&& ! TREE_PUBLIC (x)
&& (TREE_CODE (x) == FUNCTION_DECL || b == global_binding_level)
&& 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)
{
TREE_ASM_WRITTEN (t) = TREE_ASM_WRITTEN (x);
return t;
}
return t;
}
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_USED (tt) = TREE_USED (x);
TREE_TYPE (x) = tt;
}
}
if (TREE_PUBLIC (x)
&& ! (TREE_CODE (x) == FUNCTION_DECL && 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)
decl = IDENTIFIER_LIMBO_VALUE (name);
else
decl = 0;
if (decl && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl))
&& !DECL_BUILT_IN (decl))
{
pedwarn_with_decl (x,
"type mismatch with previous external decl");
pedwarn_with_decl (decl, "previous external decl of `%s'");
}
}
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'");
}
if (flag_traditional && DECL_EXTERNAL (x)
&& lookup_name (name) == 0)
{
tree type = TREE_TYPE (x);
while (type)
{
if (type == error_mark_node)
break;
if (TYPE_CONTEXT (type))
{
warning_with_decl (x, "type of external `%s' is not global");
break;
}
else if (TREE_CODE (type) == FUNCTION_TYPE
&& TYPE_ARG_TYPES (type) != 0)
break;
type = TREE_TYPE (type);
}
if (type == 0)
b = global_binding_level;
}
if (b == global_binding_level)
{
if (IDENTIFIER_GLOBAL_VALUE (name) == 0 && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
IDENTIFIER_GLOBAL_VALUE (name) = x;
IDENTIFIER_LIMBO_VALUE (name) = 0;
if (IDENTIFIER_IMPLICIT_DECL (name)
&& TREE_USED (IDENTIFIER_IMPLICIT_DECL (name)))
TREE_USED (x) = 1, TREE_USED (name) = 1;
if (IDENTIFIER_IMPLICIT_DECL (name)
&& TREE_ADDRESSABLE (IDENTIFIER_IMPLICIT_DECL (name)))
TREE_ADDRESSABLE (x) = 1;
if (IDENTIFIER_IMPLICIT_DECL (name) != 0
&& ! (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 (TREE_PUBLIC (name)
&& ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x))
{
if (t != 0 && DECL_BUILT_IN (t))
;
else if (t != 0 && DECL_BUILT_IN_NONANSI (t))
;
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
{
tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
IDENTIFIER_LOCAL_VALUE (name) = x;
if (oldlocal == 0
&& oldglobal != 0
&& TREE_CODE (x) == FUNCTION_DECL
&& TREE_CODE (oldglobal) == FUNCTION_DECL
&& DECL_EXTERNAL (x)
&& ! DECL_DECLARED_INLINE_P (x))
{
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
{
if (DECL_DECLARED_INLINE_P (oldglobal))
{
DECL_DECLARED_INLINE_P (x)
= DECL_DECLARED_INLINE_P (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_NUM_STMTS (x) = DECL_NUM_STMTS (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_ABSTRACT_ORIGIN (oldglobal);
}
if (DECL_BUILT_IN (oldglobal))
{
DECL_BUILT_IN_CLASS (x) = DECL_BUILT_IN_CLASS (oldglobal);
DECL_FUNCTION_CODE (x) = DECL_FUNCTION_CODE (oldglobal);
}
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
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 (oldlocal == 0
&& DECL_EXTERNAL (x)
&& TREE_PUBLIC (x))
{
if (oldglobal == 0)
TREE_PUBLIC (name) = 1;
if (IDENTIFIER_LIMBO_VALUE (name) == 0)
IDENTIFIER_LIMBO_VALUE (name) = x;
}
warn_if_shadowing (x, oldlocal);
if (oldlocal != 0)
b->shadowed = tree_cons (name, oldlocal, b->shadowed);
}
if (TREE_TYPE (x) != error_mark_node
&& !COMPLETE_TYPE_P (TREE_TYPE (x)))
{
tree element = TREE_TYPE (x);
while (TREE_CODE (element) == ARRAY_TYPE)
element = TREE_TYPE (element);
if (TREE_CODE (element) == RECORD_TYPE
|| TREE_CODE (element) == UNION_TYPE)
b->incomplete_list = tree_cons (NULL_TREE, x, b->incomplete_list);
}
}
TREE_CHAIN (x) = b->names;
b->names = x;
return x;
}
tree
pushdecl_top_level (x)
tree x;
{
tree t;
struct binding_level *b = current_binding_level;
current_binding_level = global_binding_level;
t = pushdecl (x);
current_binding_level = b;
return t;
}
tree
implicitly_declare (functionid)
tree functionid;
{
tree decl;
int traditional_warning = 0;
int implicit_warning;
#if 0
if (IDENTIFIER_IMPLICIT_DECL (functionid) != 0)
decl = IDENTIFIER_IMPLICIT_DECL (functionid);
else
#endif
decl = build_decl (FUNCTION_DECL, functionid, default_function_type);
if (TREE_PUBLIC (functionid) && IDENTIFIER_GLOBAL_VALUE (functionid) == 0)
traditional_warning = 1;
implicit_warning = (IDENTIFIER_IMPLICIT_DECL (functionid) == 0);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
IDENTIFIER_IMPLICIT_DECL (functionid) = decl;
pushdecl (decl);
if (compiling_objc)
objc_check_decl (decl);
rest_of_decl_compilation (decl, NULL, 0, 0);
if (implicit_warning)
implicit_decl_warning (functionid);
else if (warn_traditional && traditional_warning)
warning ("function `%s' was previously declared within a block",
IDENTIFIER_POINTER (functionid));
gen_aux_info_record (decl, 0, 1, 0);
decl_attributes (&decl, NULL_TREE, 0);
return decl;
}
void
implicit_decl_warning (id)
tree id;
{
const char *name = IDENTIFIER_POINTER (id);
if (flag_altivec && IDENTIFIER_GLOBAL_VALUE (id)
&& DECL_BUILT_IN_CLASS (IDENTIFIER_GLOBAL_VALUE (id)) == BUILT_IN_MD)
return;
if (mesg_implicit_function_declaration == 2)
error ("implicit declaration of function `%s'", name);
else if (mesg_implicit_function_declaration == 1)
warning ("implicit declaration of function `%s'", name);
}
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;
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)
{
if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0
&& ! (DECL_DECLARED_INLINE_P (olddecl) && DECL_EXTERNAL (olddecl)
&& ! (DECL_DECLARED_INLINE_P (newdecl)
&& DECL_EXTERNAL (newdecl))))
return 1;
return 0;
}
else if (DECL_CONTEXT (newdecl) == NULL_TREE)
{
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return 0;
if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0)
return 1;
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
{
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))
&& DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl))
return 2;
return 0;
}
}
tree
lookup_label (id)
tree id;
{
tree decl = IDENTIFIER_LABEL_VALUE (id);
if (current_function_decl == 0)
{
error ("label %s referenced outside of any function",
IDENTIFIER_POINTER (id));
return 0;
}
if (decl != 0)
{
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);
DECL_CONTEXT (decl) = current_function_decl;
DECL_MODE (decl) = VOIDmode;
DECL_SOURCE_LINE (decl) = lineno;
DECL_SOURCE_FILE (decl) = PFE_SAVESTRING ((char *)input_filename);
IDENTIFIER_LABEL_VALUE (id) = decl;
named_labels = tree_cons (NULL_TREE, decl, named_labels);
return decl;
}
tree
shadow_label (name)
tree name;
{
tree decl = IDENTIFIER_LABEL_VALUE (name);
if (decl != 0)
{
tree dup;
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");
return lookup_label (name);
}
shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
IDENTIFIER_LABEL_VALUE (name) = decl = 0;
}
return lookup_label (name);
}
tree
define_label (filename, line, name)
const char *filename;
int line;
tree name;
{
tree decl = lookup_label (name);
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 (warn_traditional && !in_system_header && lookup_name (name))
warning_with_file_and_line (filename, line,
"traditional C lacks a separate namespace for labels, identifier `%s' conflicts",
IDENTIFIER_POINTER (name));
if (DECL_INITIAL (decl) != 0)
{
error_with_file_and_line (filename, line, "duplicate label `%s'",
IDENTIFIER_POINTER (name));
return 0;
}
else
{
DECL_INITIAL (decl) = error_mark_node;
DECL_SOURCE_FILE (decl) = filename;
DECL_SOURCE_LINE (decl) = line;
return decl;
}
}
tree
getdecls ()
{
return current_binding_level->names;
}
tree
gettags ()
{
return current_binding_level->tags;
}
static void
storedecls (decls)
tree decls;
{
current_binding_level->names = decls;
}
static void
storetags (tags)
tree tags;
{
current_binding_level->tags = tags;
}
static tree
lookup_tag (code, name, binding_level, thislevel_only)
enum tree_code code;
struct binding_level *binding_level;
tree name;
int thislevel_only;
{
struct binding_level *level;
int thislevel = 1;
for (level = binding_level; level; level = level->level_chain)
{
tree tail;
for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
{
if (TREE_PURPOSE (tail) == name)
{
if (TREE_CODE (TREE_VALUE (tail)) != code)
{
pending_invalid_xref = name;
pending_invalid_xref_file = input_filename;
pending_invalid_xref_line = lineno;
if (thislevel)
pending_xref_error ();
}
return TREE_VALUE (tail);
}
}
if (! level->tag_transparent)
{
if (thislevel_only)
return NULL_TREE;
thislevel = 0;
}
}
return NULL_TREE;
}
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;
}
static tree
lookup_tag_reverse (type)
tree type;
{
struct binding_level *level;
for (level = current_binding_level; level; level = level->level_chain)
{
tree tail;
for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
{
if (TREE_VALUE (tail) == type)
return TREE_PURPOSE (tail);
}
}
return NULL_TREE;
}
tree
lookup_name (name)
tree name;
{
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;
}
tree
lookup_name_current_level (name)
tree name;
{
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;
}
static void
mark_binding_level (arg)
void *arg;
{
struct binding_level *level = *(struct binding_level **) arg;
for (; level != 0; level = level->level_chain)
{
ggc_mark_tree (level->names);
ggc_mark_tree (level->tags);
ggc_mark_tree (level->shadowed);
ggc_mark_tree (level->blocks);
ggc_mark_tree (level->this_block);
ggc_mark_tree (level->parm_order);
ggc_mark_tree (level->incomplete_list);
}
}
void
c_init_decl_processing ()
{
tree endlink;
tree ptr_ftype_void, ptr_ftype_ptr;
c_parse_init ();
current_function_decl = NULL;
named_labels = NULL;
current_binding_level = NULL_BINDING_LEVEL;
free_binding_level = NULL_BINDING_LEVEL;
pushlevel (0);
global_binding_level = current_binding_level;
build_common_tree_nodes (flag_signed_char);
c_common_nodes_and_builtins ();
boolean_type_node = integer_type_node;
boolean_true_node = integer_one_node;
boolean_false_node = integer_zero_node;
#ifndef BOOL_TYPE_SIZE
#define BOOL_TYPE_SIZE CHAR_TYPE_SIZE
#endif
c_bool_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
TREE_SET_CODE (c_bool_type_node, BOOLEAN_TYPE);
TYPE_MAX_VALUE (c_bool_type_node) = build_int_2 (1, 0);
TREE_TYPE (TYPE_MAX_VALUE (c_bool_type_node)) = c_bool_type_node;
TYPE_PRECISION (c_bool_type_node) = 1;
pushdecl (build_decl (TYPE_DECL, get_identifier ("_Bool"),
c_bool_type_node));
c_bool_false_node = build_int_2 (0, 0);
TREE_TYPE (c_bool_false_node) = c_bool_type_node;
c_bool_true_node = build_int_2 (1, 0);
TREE_TYPE (c_bool_true_node) = c_bool_type_node;
endlink = void_list_node;
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));
if (TYPE_PRECISION (float_type_node)
== TYPE_PRECISION (long_integer_type_node))
{
g77_integer_type_node = long_integer_type_node;
g77_uinteger_type_node = long_unsigned_type_node;
}
else if (TYPE_PRECISION (float_type_node)
== TYPE_PRECISION (integer_type_node))
{
g77_integer_type_node = integer_type_node;
g77_uinteger_type_node = unsigned_type_node;
}
else
g77_integer_type_node = g77_uinteger_type_node = NULL_TREE;
if (g77_integer_type_node != NULL_TREE)
{
pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_integer"),
g77_integer_type_node));
pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_uinteger"),
g77_uinteger_type_node));
}
if (TYPE_PRECISION (float_type_node) * 2
== TYPE_PRECISION (long_integer_type_node))
{
g77_longint_type_node = long_integer_type_node;
g77_ulongint_type_node = long_unsigned_type_node;
}
else if (TYPE_PRECISION (float_type_node) * 2
== TYPE_PRECISION (long_long_integer_type_node))
{
g77_longint_type_node = long_long_integer_type_node;
g77_ulongint_type_node = long_long_unsigned_type_node;
}
else
g77_longint_type_node = g77_ulongint_type_node = NULL_TREE;
if (g77_longint_type_node != NULL_TREE)
{
pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_longint"),
g77_longint_type_node));
pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_ulongint"),
g77_ulongint_type_node));
}
pedantic_lvalues = pedantic;
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
incomplete_decl_finalize_hook = finish_incomplete_decl;
#ifdef ENABLE_DMP_TREE
c_prev_lang_dump_tree_p = set_dump_tree_p (c_dump_tree_p);
SET_MAX_DMP_TREE_CODE(LAST_C_TREE_CODE);
#endif
ggc_add_tree_root (c_global_trees, CTI_MAX);
ggc_add_root (&c_stmt_tree, 1, sizeof c_stmt_tree, mark_stmt_tree);
ggc_add_tree_root (&c_scope_stmt_stack, 1);
ggc_add_tree_root (&named_labels, 1);
ggc_add_tree_root (&shadowed_labels, 1);
ggc_add_root (¤t_binding_level, 1, sizeof current_binding_level,
mark_binding_level);
ggc_add_root (&label_level_chain, 1, sizeof label_level_chain,
mark_binding_level);
ggc_add_tree_root (&static_ctors, 1);
ggc_add_tree_root (&static_dtors, 1);
}
static tree
c_make_fname_decl (id, type_dep)
tree id;
int type_dep;
{
const char *name = fname_as_string (type_dep);
tree decl, type, init;
size_t length = strlen (name);
type = build_array_type
(build_qualified_type (char_type_node, TYPE_QUAL_CONST),
build_index_type (size_int (length)));
decl = build_decl (VAR_DECL, id, type);
DECL_CONTEXT (decl) = current_function_decl;
TREE_STATIC (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
init = build_string (length + 1, name);
TREE_TYPE (init) = type;
DECL_INITIAL (decl) = init;
TREE_USED (decl) = 1;
finish_decl (decl, init, NULL_TREE);
return decl;
}
tree
builtin_function (name, type, function_code, class, library_name)
const char *name;
tree type;
int function_code;
enum built_in_class class;
const char *library_name;
{
tree decl = NULL;
#ifdef PFE
if (pfe_operation == PFE_LOAD)
{
decl = lookup_name_current_level ( get_identifier (name));
if (decl)
return decl;
}
#endif
decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
if (flag_traditional && name[0] != '_')
DECL_BUILT_IN_NONANSI (decl) = 1;
if (library_name)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
make_decl_rtl (decl, NULL);
pushdecl (decl);
DECL_BUILT_IN_CLASS (decl) = class;
DECL_FUNCTION_CODE (decl) = function_code;
if (function_code == BUILT_IN_RETURN || function_code == BUILT_IN_EH_RETURN)
TREE_THIS_VOLATILE (decl) = 1;
if (name[0] != '_' || name[1] != '_')
C_DECL_ANTICIPATED (decl) = 1;
decl_attributes (&decl, NULL_TREE, 0);
return decl;
}
tree lang_build_type_variant PARAMS ((tree, int, int));
tree
lang_build_type_variant (type, constp, volatilep)
tree type;
int constp, volatilep;
{
return c_build_type_variant (type, constp, volatilep);
}
void
insert_default_attributes (decl)
tree decl;
{
if (!TREE_PUBLIC (decl))
return;
c_common_insert_default_attributes (decl);
}
void
shadow_tag (declspecs)
tree declspecs;
{
shadow_tag_warned (declspecs, 0);
}
void
shadow_tag_warned (declspecs, warned)
tree declspecs;
int warned;
{
int found_tag = 0;
tree link;
tree specs, attrs;
pending_invalid_xref = 0;
split_specs_attrs (declspecs, &specs, &attrs);
for (link = specs; link; link = TREE_CHAIN (link))
{
tree value = TREE_VALUE (link);
enum tree_code code = TREE_CODE (value);
if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
{
tree name = lookup_tag_reverse (value);
tree t;
found_tag++;
if (name == 0)
{
if (warned != 1 && code != ENUMERAL_TYPE)
{
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");
}
}
tree
build_array_declarator (expr, quals, static_p, vla_unspec_p)
tree expr;
tree quals;
int static_p;
int vla_unspec_p;
{
tree decl;
decl = build_nt (ARRAY_REF, NULL_TREE, expr);
TREE_TYPE (decl) = quals;
TREE_STATIC (decl) = (static_p ? 1 : 0);
if (pedantic && !flag_isoc99)
{
if (static_p || quals != NULL_TREE)
pedwarn ("ISO C89 does not support `static' or type qualifiers in parameter array declarators");
if (vla_unspec_p)
pedwarn ("ISO C89 does not support `[*]' array declarators");
}
if (vla_unspec_p)
warning ("GCC does not yet properly implement `[*]' array declarators");
return decl;
}
tree
set_array_declarator_type (decl, type, abstract_p)
tree decl;
tree type;
int abstract_p;
{
TREE_OPERAND (decl, 0) = type;
if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
error ("static or type qualifiers in abstract declarator");
return decl;
}
tree
groktypename (typename)
tree typename;
{
tree specs, attrs;
if (TREE_CODE (typename) != TREE_LIST)
return typename;
split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
typename = grokdeclarator (TREE_VALUE (typename), specs, TYPENAME, 0);
decl_attributes (&typename, attrs, 0);
return typename;
}
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);
}
tree
start_decl (declarator, declspecs, initialized, attributes)
tree declarator, declspecs;
int initialized;
tree attributes;
{
tree decl;
tree tem;
#ifdef A_LESS_INEFFICENT_WAY
if (lookup_attribute ("deprecated", attributes))
deprecated_state = DEPRECATED_SUPPRESS;
else if (lookup_attribute ("unavailable", attributes))
deprecated_state = DEPRECATED_UNAVAILABLE_SUPPRESS;
#else
tree a;
for (a = attributes; a; a = TREE_CHAIN (a))
{
tree name = TREE_PURPOSE (a);
if (TREE_CODE (name) == IDENTIFIER_NODE)
if (is_attribute_p ("deprecated", name))
{
deprecated_state = DEPRECATED_SUPPRESS;
break;
}
if (is_attribute_p ("unavailable", name))
{
deprecated_state = DEPRECATED_UNAVAILABLE_SUPPRESS;
break;
}
}
#endif
decl = grokdeclarator (declarator, declspecs,
NORMAL, initialized);
deprecated_state = DEPRECATED_NORMAL;
if (flag_gen_index)
{
int t;
switch (TREE_CODE (decl))
{
case FUNCTION_DECL:
t = INDEX_FUNCTION_DECL;
break;
case CONST_DECL:
t = INDEX_CONST_DECL;
break;
case VAR_DECL:
t = INDEX_VAR_DECL;
break;
case TYPE_DECL:
t = INDEX_TYPE_DECL;
break;
case PARM_DECL:
default:
t = INDEX_ERROR;
break;
}
if (TREE_CODE (decl) != PARM_DECL)
gen_indexing_info (t, IDENTIFIER_POINTER (DECL_NAME (decl)),
DECL_SOURCE_LINE (decl));
}
if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
&& MAIN_NAME_P (DECL_NAME (decl)))
warning_with_decl (decl, "`%s' is usually a function");
if (initialized)
switch (TREE_CODE (decl))
{
case TYPE_DECL:
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:
error ("parameter `%s' is initialized",
IDENTIFIER_POINTER (DECL_NAME (decl)));
initialized = 0;
break;
default:
if (TREE_TYPE (decl) == error_mark_node)
initialized = 0;
else if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
{
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 (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
{
error ("elements of array `%s' have incomplete type",
IDENTIFIER_POINTER (DECL_NAME (decl)));
initialized = 0;
}
}
if (initialized)
{
#if 0
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;
DECL_INITIAL (decl) = error_mark_node;
}
if (TREE_CODE (decl) == FUNCTION_DECL)
gen_aux_info_record (decl, 0, 0, TYPE_ARG_TYPES (TREE_TYPE (decl)) != 0);
if (! flag_no_common || ! TREE_PUBLIC (decl))
DECL_COMMON (decl) = 1;
decl_attributes (&decl, attributes, 0);
if (current_binding_level == global_binding_level)
maybe_apply_pragma_weak (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
warning_with_decl (decl,
"inline function `%s' given attribute noinline");
tem = pushdecl (decl);
if (current_binding_level != global_binding_level
&& !DECL_RTL_SET_P (tem)
&& !DECL_CONTEXT (tem))
{
if (TREE_TYPE (tem) != error_mark_node
&& COMPLETE_TYPE_P (TREE_TYPE (tem)))
expand_decl (tem);
else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
&& DECL_INITIAL (tem) != 0)
expand_decl (tem);
}
return tem;
}
void
finish_decl (decl, init, asmspec_tree)
tree decl, init;
tree asmspec_tree;
{
tree type = TREE_TYPE (decl);
int was_incomplete = (DECL_SIZE (decl) == 0);
const char *asmspec = 0;
if (current_binding_level == global_binding_level)
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
if (init != 0 && DECL_INITIAL (decl) == 0)
init = 0;
if (TREE_CODE (decl) == PARM_DECL)
init = 0;
if (init)
{
if (TREE_CODE (decl) != TYPE_DECL)
store_init_value (decl, init);
else
{
TREE_TYPE (decl) = TREE_TYPE (init);
DECL_INITIAL (decl) = init = 0;
}
}
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == 0
&& TREE_CODE (decl) != TYPE_DECL)
{
int do_default
= (TREE_STATIC (decl)
? pedantic && !TREE_PUBLIC (decl)
: !DECL_EXTERNAL (decl));
int failure
= complete_array_type (type, DECL_INITIAL (decl), do_default);
type = TREE_TYPE (decl);
if (failure == 1)
error_with_decl (decl, "initializer fails to determine size of `%s'");
else if (failure == 2)
{
if (do_default)
error_with_decl (decl, "array size missing in `%s'");
else if (!pedantic && TREE_STATIC (decl) && ! TREE_PUBLIC (decl))
DECL_EXTERNAL (decl) = 1;
}
else 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 && TREE_TYPE (decl) != error_mark_node
&& COMPLETE_TYPE_P (TREE_TYPE (decl)))
layout_decl (decl, 0);
if (DECL_SIZE (decl) == 0
&& TREE_TYPE (decl) != error_mark_node
&& (TREE_STATIC (decl)
?
(DECL_INITIAL (decl) != 0
|| DECL_CONTEXT (decl) != 0)
:
!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 (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
{
DECL_BUILT_IN_CLASS (decl) = NOT_BUILT_IN;
SET_DECL_RTL (decl, NULL_RTX);
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
}
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
{
if (compiling_objc)
objc_check_decl (decl);
if (!DECL_CONTEXT (decl))
{
if (DECL_INITIAL (decl) == NULL_TREE
|| DECL_INITIAL (decl) == error_mark_node)
DECL_DEFER_OUTPUT (decl) = 1;
rest_of_decl_compilation (decl, asmspec,
(DECL_CONTEXT (decl) == 0
|| TREE_ASM_WRITTEN (decl)), 0);
}
else
{
if (asmspec)
{
if (DECL_REGISTER (decl))
DECL_C_HARD_REGISTER (decl) = 1;
if (TREE_CODE (decl) == VAR_DECL
&& !DECL_REGISTER (decl)
&& !TREE_STATIC (decl))
warning_with_decl (decl,
"ignoring asm-specifier for non-static local variable `%s'");
else
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
}
if (TREE_CODE (decl) != FUNCTION_DECL)
add_decl_stmt (decl);
}
if (DECL_CONTEXT (decl) != 0)
{
if (was_incomplete
&& ! TREE_STATIC (decl) && ! DECL_EXTERNAL (decl))
{
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
if (DECL_SIZE (decl) == 0)
DECL_INITIAL (decl) = 0;
}
}
}
if (TREE_CODE (decl) == TYPE_DECL)
{
if (compiling_objc)
objc_check_decl (decl);
rest_of_decl_compilation (decl, NULL, DECL_CONTEXT (decl) == 0, 0);
}
if (current_binding_level == global_binding_level)
get_pending_sizes ();
}
tree
maybe_build_cleanup (decl)
tree decl ATTRIBUTE_UNUSED;
{
return NULL_TREE;
}
void
push_parm_decl (parm)
tree parm;
{
tree decl;
int old_immediate_size_expand = immediate_size_expand;
immediate_size_expand = 0;
decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
TREE_PURPOSE (TREE_PURPOSE (parm)), PARM, 0);
decl_attributes (&decl, TREE_VALUE (parm), 0);
#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,
"ISO 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);
finish_decl (decl, NULL_TREE, NULL_TREE);
}
void
clear_parm_order ()
{
current_binding_level->parm_order = NULL_TREE;
}
tree
build_compound_literal (type, init)
tree type;
tree init;
{
tree decl = build_decl (VAR_DECL, NULL_TREE, type);
tree complit;
tree stmt;
DECL_EXTERNAL (decl) = 0;
TREE_PUBLIC (decl) = 0;
TREE_STATIC (decl) = (current_binding_level == global_binding_level);
DECL_CONTEXT (decl) = current_function_decl;
TREE_USED (decl) = 1;
TREE_TYPE (decl) = type;
store_init_value (decl, init);
if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
{
int failure = complete_array_type (type, DECL_INITIAL (decl), 1);
if (failure)
abort ();
}
type = TREE_TYPE (decl);
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
return error_mark_node;
stmt = build_stmt (DECL_STMT, decl);
complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
TREE_SIDE_EFFECTS (complit) = 1;
layout_decl (decl, 0);
if (TREE_STATIC (decl))
{
DECL_NAME (decl) = get_identifier ("__compound_literal");
DECL_CONTEXT (decl) = complit;
rest_of_decl_compilation (decl, NULL, 1, 0);
DECL_CONTEXT (decl) = NULL_TREE;
}
return complit;
}
int
complete_array_type (type, initial_value, do_default)
tree type;
tree initial_value;
int do_default;
{
tree maxindex = NULL_TREE;
int value = 0;
if (initial_value)
{
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 = build_int_2 (-1, -1);
for (; elts; elts = TREE_CHAIN (elts))
{
if (TREE_PURPOSE (elts))
maxindex = TREE_PURPOSE (elts);
else
maxindex = fold (build (PLUS_EXPR, integer_type_node,
maxindex, integer_one_node));
}
maxindex = copy_node (maxindex);
}
else
{
if (initial_value != error_mark_node)
value = 1;
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);
}
layout_type (type);
return value;
}
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 explicit_bool = 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_attr = NULL_TREE;
tree array_ptr_quals = NULL_TREE;
int array_parm_static = 0;
tree returned_attrs = NULL_TREE;
if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
if (decl_context == FUNCDEF)
funcdef_flag = 1, decl_context = NORMAL;
{
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 TREE_LIST:
decl = TREE_VALUE (decl);
break;
case IDENTIFIER_NODE:
name = IDENTIFIER_POINTER (decl);
decl = 0;
break;
default:
abort ();
}
if (name == 0)
name = "type name";
}
if (funcdef_flag && innermost_code != CALL_EXPR)
return 0;
if (decl_context == NORMAL && !funcdef_flag
&& current_binding_level->parm_flag)
decl_context = PARM;
for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
{
tree id = TREE_VALUE (spec);
if (id && TREE_DEPRECATED (id))
{
if (TREE_UNAVAILABLE (id))
{
if (deprecated_state != DEPRECATED_UNAVAILABLE_SUPPRESS)
warn_deprecated_use (id);
#if 0
returned_attrs
= chainon (returned_attrs,
build_tree_list (get_identifier ("unavailable"),
NULL_TREE));
#endif
}
else
{
if (deprecated_state != DEPRECATED_SUPPRESS
&& deprecated_state != DEPRECATED_UNAVAILABLE_SUPPRESS)
warn_deprecated_use (id);
#if 0
returned_attrs
= chainon (returned_attrs,
build_tree_list (get_identifier ("deprecated"),
NULL_TREE));
#endif
}
}
if (id == ridpointers[(int) RID_INT]) {
explicit_int = 1;
if (flag_altivec && explicit_bool) {
type = NULL_TREE;
specbits |= (1 << (int) RID_ALTIVEC_BOOL);
}
}
if (id == ridpointers[(int) RID_CHAR]) {
explicit_char = 1;
if (flag_altivec && explicit_bool) {
type = NULL_TREE;
specbits |= (1 << (int) RID_ALTIVEC_BOOL);
}
}
if (TREE_CODE (id) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (id))
{
enum rid i = C_RID_CODE (id);
if (i == RID_BOOL || i == RID_ALTIVEC_BOOL)
{
explicit_bool = 1;
if (flag_altivec && type)
i = RID_ALTIVEC_BOOL;
}
if ((int) i <= (int) RID_LAST_MODIFIER)
{
if (i == RID_LONG && (specbits & (1 << (int) i)))
{
if (longlong)
error ("`long long long' is too long for GCC");
else
{
if (pedantic && !flag_isoc99 && ! in_system_header
&& warn_long_long)
pedwarn ("ISO C89 does not support `long long'");
longlong = 1;
}
}
else if (specbits & (1 << (int) i))
pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
specbits |= 1 << (int) i;
goto found;
}
}
if (type)
error ("two or more data types in declaration of `%s'", name);
else if (TREE_CODE (id) == TYPE_DECL)
{
if (TREE_TYPE (id) == error_mark_node)
;
else
{
type = TREE_TYPE (id);
decl_attr = DECL_ATTRIBUTES (id);
typedef_decl = id;
}
}
else if (TREE_CODE (id) == IDENTIFIER_NODE)
{
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);
if (type == 0)
{
if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
| (1 << (int) RID_SIGNED)
| (1 << (int) RID_UNSIGNED)
| (1 << (int) RID_COMPLEX)
| (1 << (int) RID_ALTIVEC_VECTOR)
| (1 << (int) RID_ALTIVEC_PIXEL))))
&& ! (specbits & (1 << (int) RID_TYPEDEF) && initialized)
&& ! in_system_header)
{
if ((warn_implicit_int || warn_return_type || flag_isoc99)
&& funcdef_flag)
warn_about_return_type = 1;
else if (warn_implicit_int || flag_isoc99)
pedwarn_c99 ("type defaults to `int' in declaration of `%s'",
name);
}
defaulted_int = 1;
type = integer_type_node;
}
if ((specbits & 1 << (int) RID_LONG) && ! longlong
&& TYPE_MAIN_VARIANT (type) == double_type_node)
{
specbits &= ~(1 << (int) RID_LONG);
type = long_double_type_node;
warn_about_long_double ();
}
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
&& (!flag_altivec || TREE_CODE (type) != BOOLEAN_TYPE))
error ("long, short, signed or unsigned invalid for `%s'", name);
else
{
ok = 1;
if (!explicit_int && !explicit_bool && !defaulted_int
&& !explicit_char && pedantic)
{
pedwarn ("long, short, signed or unsigned used invalidly for `%s'",
name);
if (flag_pedantic_errors)
ok = 0;
}
}
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);
}
if (specbits & 1 << (int) RID_UNSIGNED
|| (bitfield && flag_traditional
&& (! explicit_flag_signed_bitfields || !flag_signed_bitfields))
|| (bitfield && ! flag_signed_bitfields
&& (explicit_int || defaulted_int || explicit_char
|| ! (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 (pedantic && !flag_isoc99)
pedwarn ("ISO C89 does not support complex types");
if (defaulted_int && ! longlong
&& ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
| (1 << (int) RID_SIGNED)
| (1 << (int) RID_UNSIGNED))))
{
if (pedantic)
pedwarn ("ISO C does not support plain `complex' meaning `double complex'");
type = complex_double_type_node;
}
else if (type == integer_type_node)
{
if (pedantic)
pedwarn ("ISO C does not support complex integer types");
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
{
if (pedantic)
pedwarn ("ISO C does not support complex integer types");
type = build_complex_type (type);
}
}
if ((specbits & (1 << (int) RID_ALTIVEC_PIXEL))
&& !(specbits & (1 << (int) RID_ALTIVEC_VECTOR)))
{
error ("__pixel invalid for `%s'", name);
specbits &= ~ (1 << (int) RID_ALTIVEC_PIXEL);
}
if (specbits & 1 << (int) RID_ALTIVEC_VECTOR)
{
if ((type == integer_type_node || type == long_integer_type_node)
&& !explicit_bool && !explicit_int
&& (specbits & (1 << (int) RID_ALTIVEC_PIXEL)))
type = vector_pixel_type_node;
else if (type == long_unsigned_type_node)
{
type = vector_unsigned_long_type_node;
if (warn_altivec_long_deprecated)
warning ("Use of 'long' in AltiVec types is deprecated; use 'int'");
}
else if (type == unsigned_type_node
&& explicit_int && !explicit_bool)
type = vector_unsigned_long_type_node;
else if ((type == long_integer_type_node && explicit_bool)
|| (type == integer_type_node && explicit_int
&& explicit_bool && !(specbits & 1 << (int) RID_SIGNED)))
{
if (warn_altivec_long_deprecated && type == long_integer_type_node)
warning ("Use of 'long' in AltiVec types is deprecated; use 'int'");
type = vector_boolean_long_type_node;
}
else if ((type == long_integer_type_node && !explicit_bool)
|| (type == integer_type_node && explicit_int
&& !explicit_bool && (specbits & 1 << (int) RID_SIGNED)))
{
if (warn_altivec_long_deprecated && type == long_integer_type_node)
warning ("Use of 'long' in AltiVec types is deprecated; use 'int'");
type = vector_signed_long_type_node;
}
else if (type == short_unsigned_type_node)
type = vector_unsigned_short_type_node;
else if (type == short_integer_type_node)
type = (explicit_bool
? vector_boolean_short_type_node
: vector_signed_short_type_node);
else if (type == unsigned_char_type_node || explicit_char && type == unsigned_type_node)
type = vector_unsigned_char_type_node;
else if (type == signed_char_type_node || explicit_char && type == integer_type_node)
type = vector_signed_char_type_node;
else if (type == char_type_node && explicit_bool)
type = vector_boolean_char_type_node;
else if (type == float_type_node)
type = vector_float_type_node;
else
{
error ("vector invalid for `%s'", name);
specbits &= ~ ((1 << (int) RID_ALTIVEC_VECTOR) | (1 << (int) RID_ALTIVEC_PIXEL));
}
if ((specbits & (1 << (int) RID_ALTIVEC_PIXEL))
&& type != vector_pixel_type_node)
{
error ("type modifiers do not apply to `vector pixel'");
type = vector_pixel_type_node;
}
}
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 && ! flag_isoc99)
pedwarn ("duplicate `const'");
if (restrictp > 1 && ! flag_isoc99)
pedwarn ("duplicate `restrict'");
if (volatilep > 1 && ! flag_isoc99)
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));
{
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_PRIVATE_EXTERN) nclasses++;
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
{
switch (decl_context)
{
case FIELD:
error ("storage class specified for structure field `%s'",
name);
break;
case PARM:
error ("storage class specified for parameter `%s'", name);
break;
default:
error ("storage class specified for typename");
break;
}
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)
{
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);
}
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE)
{
if (type == error_mark_node)
{
declarator = TREE_OPERAND (declarator, 0);
continue;
}
if (array_ptr_quals != NULL_TREE || array_parm_static)
{
error ("static or type qualifiers in non-parameter array declarator");
array_ptr_quals = NULL_TREE;
array_parm_static = 0;
}
if (TREE_CODE (declarator) == TREE_LIST)
{
tree attrs = TREE_PURPOSE (declarator);
tree inner_decl;
int attr_flags = 0;
declarator = TREE_VALUE (declarator);
inner_decl = declarator;
while (inner_decl != NULL_TREE
&& TREE_CODE (inner_decl) == TREE_LIST)
inner_decl = TREE_VALUE (inner_decl);
if (inner_decl == NULL_TREE
|| TREE_CODE (inner_decl) == IDENTIFIER_NODE)
attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
else if (TREE_CODE (inner_decl) == CALL_EXPR)
attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
else if (TREE_CODE (inner_decl) == ARRAY_REF)
attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
returned_attrs = decl_attributes (&type,
chainon (returned_attrs, attrs),
attr_flags);
}
else if (TREE_CODE (declarator) == ARRAY_REF)
{
tree itype = NULL_TREE;
tree size = TREE_OPERAND (declarator, 1);
tree index_type = signed_type (sizetype);
array_ptr_quals = TREE_TYPE (declarator);
array_parm_static = TREE_STATIC (declarator);
declarator = TREE_OPERAND (declarator, 0);
if (VOID_TYPE_P (type))
{
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 (size)
{
STRIP_TYPE_NOPS (size);
if (! INTEGRAL_TYPE_P (TREE_TYPE (size)))
{
error ("size of array `%s' has non-integer type", name);
size = integer_one_node;
}
if (pedantic && integer_zerop (size))
pedwarn ("ISO 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
{
size_varies = 1;
if (pedantic)
{
if (TREE_CONSTANT (size))
pedwarn ("ISO C89 forbids array `%s' whose size can't be evaluated",
name);
else
pedwarn ("ISO C89 forbids variable-size array `%s'",
name);
}
}
if (integer_zerop (size))
{
itype = build_range_type (sizetype, size, NULL_TREE);
}
else
{
itype = fold (build (MINUS_EXPR, index_type,
convert (index_type, size),
convert (index_type, size_one_node)));
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);
}
}
else if (decl_context == FIELD)
{
if (pedantic && !flag_isoc99 && !in_system_header)
pedwarn ("ISO C89 does not support flexible array members");
itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
}
if (pedantic && !COMPLETE_TYPE_P (type))
pedwarn ("array type has incomplete element type");
#if 0
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& (constp || volatilep))
pedwarn ("ISO C forbids const or volatile function types");
#endif
type = build_array_type (type, itype);
if (type_quals)
type = c_build_qualified_type (type, type_quals);
if (size_varies)
C_TYPE_VARIABLE_SIZE (type) = 1;
if (size && integer_zerop (size))
{
layout_type (type);
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
}
if (decl_context != PARM
&& (array_ptr_quals != NULL_TREE || array_parm_static))
{
error ("static or type qualifiers in non-parameter array declarator");
array_ptr_quals = NULL_TREE;
array_parm_static = 0;
}
}
else if (TREE_CODE (declarator) == CALL_EXPR)
{
tree arg_types;
if (type == error_mark_node)
continue;
size_varies = 0;
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
if (flag_traditional && TYPE_MAIN_VARIANT (type) == float_type_node)
type = double_type_node;
#endif
arg_types = grokparms (TREE_OPERAND (declarator, 1),
funcdef_flag
&& TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE);
if (type_quals)
{
if (VOID_TYPE_P (type) && pedantic && !in_system_header)
pedwarn ("ISO C forbids qualified void function return type");
else if (extra_warnings
&& !(VOID_TYPE_P (type)
&& type_quals == TYPE_QUAL_VOLATILE))
warning ("type qualifiers ignored on function return type");
type = c_build_qualified_type (type, type_quals);
}
type_quals = TYPE_UNQUALIFIED;
type = build_function_type (type, arg_types);
declarator = TREE_OPERAND (declarator, 0);
{
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)
{
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
pedwarn ("ISO 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);
if (TREE_TYPE (declarator))
{
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 (C_IS_RESERVED_WORD (qualifier))
{
if (C_RID_CODE (qualifier) == RID_CONST)
constp++;
else if (C_RID_CODE (qualifier) == RID_VOLATILE)
volatilep++;
else if (C_RID_CODE (qualifier) == RID_RESTRICT)
restrictp++;
else
erred++;
}
else
erred++;
}
if (erred)
error ("invalid type modifier within pointer declarator");
if (constp > 1 && ! flag_isoc99)
pedwarn ("duplicate `const'");
if (volatilep > 1 && ! flag_isoc99)
pedwarn ("duplicate `volatile'");
if (restrictp > 1 && ! flag_isoc99)
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 ();
}
if (TREE_CODE (type) == ARRAY_TYPE
&& COMPLETE_TYPE_P (type)
&& TREE_OVERFLOW (TYPE_SIZE (type)))
{
error ("size of array `%s' is too large", name);
type = error_mark_node;
}
if (specbits & (1 << (int) RID_TYPEDEF))
{
tree decl;
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
pedwarn ("ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
decl = build_decl (TYPE_DECL, declarator, type);
if ((specbits & (1 << (int) RID_SIGNED))
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
decl_attributes (&decl, returned_attrs, 0);
return decl;
}
if (type != 0 && typedef_type != 0
&& TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
{
type = build_array_type (TREE_TYPE (type), 0);
if (size_varies)
C_TYPE_VARIABLE_SIZE (type) = 1;
}
if (decl_context == TYPENAME)
{
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
pedwarn ("ISO C forbids const or volatile function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
decl_attributes (&type, returned_attrs, 0);
return type;
}
if (VOID_TYPE_P (type) && 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;
}
{
tree decl;
if (decl_context == PARM)
{
tree type_as_written;
tree promoted_type;
if (TREE_CODE (type) == ARRAY_TYPE)
{
type = TREE_TYPE (type);
if (type_quals)
type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
type_quals = TYPE_UNQUALIFIED;
if (array_ptr_quals)
{
tree new_ptr_quals, new_ptr_attrs;
int erred = 0;
split_specs_attrs (array_ptr_quals, &new_ptr_quals, &new_ptr_attrs);
if (new_ptr_attrs != NULL_TREE)
warning ("attributes in parameter array declarator ignored");
constp = 0;
volatilep = 0;
restrictp = 0;
for (; new_ptr_quals; new_ptr_quals = TREE_CHAIN (new_ptr_quals))
{
tree qualifier = TREE_VALUE (new_ptr_quals);
if (C_IS_RESERVED_WORD (qualifier))
{
if (C_RID_CODE (qualifier) == RID_CONST)
constp++;
else if (C_RID_CODE (qualifier) == RID_VOLATILE)
volatilep++;
else if (C_RID_CODE (qualifier) == RID_RESTRICT)
restrictp++;
else
erred++;
}
else
erred++;
}
if (erred)
error ("invalid type modifier within array declarator");
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
| (volatilep ? TYPE_QUAL_VOLATILE : 0));
}
size_varies = 0;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
if (pedantic && type_quals)
pedwarn ("ISO 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;
}
else if (type_quals)
type = c_build_qualified_type (type, type_quals);
type_as_written = type;
decl = build_decl (PARM_DECL, declarator, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
if (type == error_mark_node)
promoted_type = type;
else
{
promoted_type = simple_type_promotes_to (type);
if (! promoted_type)
promoted_type = type;
}
DECL_ARG_TYPE (decl) = promoted_type;
DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written;
}
else if (decl_context == FIELD)
{
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
&& !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
{
error ("field `%s' has incomplete type", name);
type = error_mark_node;
}
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
type_quals = TYPE_UNQUALIFIED;
#endif
}
decl = build_decl (FIELD_DECL, declarator, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
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);
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);
decl = build_decl (FUNCTION_DECL, declarator, type);
decl = build_decl_attribute_variant (decl, decl_attr);
DECL_LANG_SPECIFIC (decl) = (struct lang_decl *)
GGC_ALLOC_CLEARED (sizeof (struct lang_decl), PFE_ALLOC_GGC_LANG_DECL);
if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ISO C forbids qualified function types");
if ((type_quals & TYPE_QUAL_VOLATILE)
&& !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
warning ("`noreturn' function returns non-void value");
if (extern_ref)
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl)
= !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
if (defaulted_int)
C_FUNCTION_IMPLICIT_INT (decl) = 1;
DECL_PRIVATE_EXTERN (decl)
= ((specbits & (1 << (int) RID_PRIVATE_EXTERN)) != 0);
if (MAIN_NAME_P (declarator))
{
if (inlinep)
warning ("cannot inline function `main'");
}
else if (inlinep)
{
DECL_DECLARED_INLINE_P (decl) = 1;
if (initialized)
{
DECL_INLINE (decl) = 1;
if (specbits & (1 << (int) RID_EXTERN))
current_extern_inline = 1;
}
}
else if (flag_inline_trees == 2 && initialized)
{
DECL_INLINE (decl) = 1;
DECL_DECLARED_INLINE_P (decl) = 0;
}
}
else
{
int extern_ref = !initialized && (specbits & ((1 << (int) RID_EXTERN)
| (1 << (int) RID_PRIVATE_EXTERN)));
if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
{
int saved_align = TYPE_ALIGN(type);
type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
type_quals),
TYPE_DOMAIN (type));
TYPE_ALIGN (type) = saved_align;
#if 0
type_quals = TYPE_UNQUALIFIED;
#endif
}
else if (type_quals)
type = c_build_qualified_type (type, type_quals);
decl = build_decl (VAR_DECL, declarator, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
if (inlinep)
pedwarn_with_decl (decl, "variable `%s' declared `inline'");
DECL_EXTERNAL (decl) = extern_ref;
DECL_PRIVATE_EXTERN (decl)
= ((specbits & (1 << (int) RID_PRIVATE_EXTERN)) != 0);
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);
}
else
{
TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
}
if (specbits & (1 << (int) RID_REGISTER))
DECL_REGISTER (decl) = 1;
c_apply_type_quals_to_decl (type_quals, decl);
if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
mark_addressable (decl);
decl_attributes (&decl, returned_attrs, 0);
return decl;
}
}
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;
#if 0
if (funcdef_flag)
#endif
for (parm = last_function_parms, typelt = first_parm;
parm;
parm = TREE_CHAIN (parm))
if (TREE_CODE (parm) == PARM_DECL)
{
tree type = TREE_VALUE (typelt);
if (type == error_mark_node)
continue;
if (!COMPLETE_TYPE_P (type))
{
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
else
{
while (TREE_CODE (type) == POINTER_TYPE
|| TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
type = TYPE_MAIN_VARIANT (type);
if (!COMPLETE_TYPE_P (type))
{
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);
}
return first_parm;
}
}
tree
get_parm_info (void_at_end)
int void_at_end;
{
tree decl, t;
tree types = 0;
int erred = 0;
tree tags = gettags ();
tree parms = getdecls ();
tree new_parms = 0;
tree order = current_binding_level->parm_order;
if (void_at_end && parms != 0
&& TREE_CHAIN (parms) == 0
&& VOID_TYPE_P (TREE_TYPE (parms))
&& ! TREE_THIS_VOLATILE (parms)
&& ! TREE_READONLY (parms)
&& ! DECL_REGISTER (parms)
&& DECL_NAME (parms) == 0)
{
parms = NULL_TREE;
storedecls (NULL_TREE);
return tree_cons (NULL_TREE, NULL_TREE,
tree_cons (NULL_TREE, void_type_node, NULL_TREE));
}
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;
}
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);
storedecls (new_parms);
for (decl = new_parms; decl; decl = TREE_CHAIN (decl))
if (TREE_CODE (decl) == PARM_DECL)
{
tree type = TREE_TYPE (decl);
DECL_ARG_TYPE (decl) = type;
if (PROMOTE_PROTOTYPES
&& INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (decl) = integer_type_node;
types = tree_cons (NULL_TREE, TREE_TYPE (decl), types);
if (VOID_TYPE_P (TREE_VALUE (types)) && ! erred
&& DECL_NAME (decl) == 0)
{
error ("`void' in parameter list must be the entire list");
erred = 1;
}
}
if (void_at_end)
return tree_cons (new_parms, tags,
nreverse (tree_cons (NULL_TREE, void_type_node, types)));
return tree_cons (new_parms, tags, nreverse (types));
}
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));
if (code == UNION_TYPE && TREE_PURPOSE (elt) == 0 && !pedantic)
continue;
if (TREE_PURPOSE (elt) != 0)
{
if (code == RECORD_TYPE)
warning ("`struct %s' declared inside parameter list",
IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
else if (code == UNION_TYPE)
warning ("`union %s' declared inside parameter list",
IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
else
warning ("`enum %s' declared inside parameter list",
IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
}
else
{
if (code == RECORD_TYPE)
warning ("anonymous struct declared inside parameter list");
else if (code == UNION_TYPE)
warning ("anonymous union declared inside parameter list");
else
warning ("anonymous enum declared inside parameter list");
}
if (! already)
{
warning ("its scope is only this definition or declaration, which is probably not what you want");
already = 1;
}
}
}
tree
xref_tag (code, name)
enum tree_code code;
tree name;
{
tree ref = lookup_tag (code, name, current_binding_level, 0);
if (ref && TREE_CODE (ref) == code)
return ref;
ref = make_node (code);
if (code == ENUMERAL_TYPE)
{
TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
TYPE_USER_ALIGN (ref) = 0;
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);
return ref;
}
tree
start_struct (code, name)
enum tree_code code;
tree name;
{
tree ref = 0;
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))
{
if (code == UNION_TYPE)
error ("redefinition of `union %s'",
IDENTIFIER_POINTER (name));
else
error ("redefinition of `struct %s'",
IDENTIFIER_POINTER (name));
}
return ref;
}
ref = make_node (code);
pushtag (name, ref);
C_TYPE_BEING_DEFINED (ref) = 1;
TYPE_PACKED (ref) = flag_pack_struct;
return ref;
}
tree
grokfield (filename, line, declarator, declspecs, width)
const char *filename ATTRIBUTE_UNUSED;
int line ATTRIBUTE_UNUSED;
tree declarator, declspecs, width;
{
tree value;
if (declarator == NULL_TREE && width == NULL_TREE)
{
if (TREE_CODE (TREE_VALUE (declspecs)) != RECORD_TYPE
&& TREE_CODE (TREE_VALUE (declspecs)) != UNION_TYPE)
{
error ("unnamed fields of type other than struct or union are not allowed");
return NULL_TREE;
}
}
value = grokdeclarator (declarator, declspecs, width ? BITFIELD : FIELD, 0);
finish_decl (value, NULL_TREE, NULL_TREE);
DECL_INITIAL (value) = width;
if (compiling_objc)
objc_check_decl (value);
return value;
}
tree
finish_struct (t, fieldlist, attributes)
tree t;
tree fieldlist;
tree attributes;
{
tree x;
int toplevel = global_binding_level == current_binding_level;
int saw_named_field;
TYPE_SIZE (t) = 0;
decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic)
if (in_parm_level_p ())
{
if (pedantic)
pedwarn ("%s defined inside parms",
TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
else if (! flag_traditional)
warning ("%s defined inside parms",
TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
}
if (pedantic)
{
for (x = fieldlist; x; x = TREE_CHAIN (x))
if (DECL_NAME (x) != 0)
break;
if (x == 0)
pedwarn ("%s has no %s",
TREE_CODE (t) == UNION_TYPE ? _("union") : _("struct"),
fieldlist ? _("named members") : _("members"));
}
saw_named_field = 0;
for (x = fieldlist; x; x = TREE_CHAIN (x))
{
DECL_CONTEXT (x) = t;
DECL_PACKED (x) |= TYPE_PACKED (t);
if (TREE_READONLY (x))
C_TYPE_FIELDS_READONLY (t) = 1;
else
{
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;
}
if (TREE_THIS_VOLATILE (x))
C_TYPE_FIELDS_VOLATILE (t) = 1;
if (C_DECL_VARIABLE_SIZE (x))
C_TYPE_VARIABLE_SIZE (t) = 1;
if (TREE_TYPE (x) == t)
error ("nested redefinition of `%s'",
IDENTIFIER_POINTER (TYPE_NAME (t)));
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;
}
}
if (DECL_INITIAL (x)
&& TREE_CODE (TREE_TYPE (x)) != INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (x)) != BOOLEAN_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
&& TYPE_MAIN_VARIANT (TREE_TYPE (x)) != c_bool_type_node
&& !(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 ISO C");
if (DECL_INITIAL (x))
{
int max_width
= (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == c_bool_type_node
? CHAR_TYPE_SIZE : TYPE_PRECISION (TREE_TYPE (x)));
if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
error_with_decl (x, "negative width in bit-field `%s'");
else if (0 < compare_tree_int (DECL_INITIAL (x), max_width))
pedwarn_with_decl (x, "width of `%s' exceeds its type");
else if (integer_zerop (DECL_INITIAL (x)) && DECL_NAME (x) != 0)
error_with_decl (x, "zero width for bit-field `%s'");
else
{
unsigned HOST_WIDE_INT width
= tree_low_cst (DECL_INITIAL (x), 1);
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_SIZE (x) = bitsize_int (width);
DECL_BIT_FIELD (x) = 1;
SET_DECL_C_BIT_FIELD (x);
if (width == 0
&& ! (* targetm.ms_bitfield_layout_p) (t))
{
#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)));
DECL_USER_ALIGN (x) |= TYPE_USER_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)));
DECL_ALIGN (x) = MAX (DECL_ALIGN (x), min_align);
if (! DECL_PACKED (x))
DECL_USER_ALIGN (x) |= TYPE_USER_ALIGN (TREE_TYPE (x));
}
DECL_INITIAL (x) = 0;
if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
&& TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
&& TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
&& TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
{
if (TREE_CODE (t) == UNION_TYPE)
error_with_decl (x, "flexible array member in union");
else if (TREE_CHAIN (x) != NULL_TREE)
error_with_decl (x, "flexible array member not at end of struct");
else if (! saw_named_field)
error_with_decl (x, "flexible array member in otherwise empty struct");
}
if (DECL_NAME (x))
saw_named_field = 1;
}
for (x = fieldlist; x && TREE_CHAIN (x);)
if (DECL_NAME (TREE_CHAIN (x)) == 0)
x = TREE_CHAIN (x);
else
{
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);
}
TYPE_FIELDS (t) = fieldlist;
layout_type (t);
{
tree *fieldlistp = &fieldlist;
while (*fieldlistp)
if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp))
*fieldlistp = TREE_CHAIN (*fieldlistp);
else
fieldlistp = &TREE_CHAIN (*fieldlistp);
}
TYPE_FIELDS (t) = fieldlist;
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);
TYPE_USER_ALIGN (x) = TYPE_USER_ALIGN (t);
}
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 (current_binding_level->incomplete_list != NULL_TREE)
{
tree prev = NULL_TREE;
for (x = current_binding_level->incomplete_list; x; x = TREE_CHAIN (x))
{
tree decl = TREE_VALUE (x);
if (TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TYPE_MAIN_VARIANT (t)
&& TREE_CODE (decl) != TYPE_DECL)
{
layout_decl (decl, 0);
if (compiling_objc)
objc_check_decl (decl);
rest_of_decl_compilation (decl, NULL, toplevel, 0);
if (! toplevel)
expand_decl (decl);
if (prev)
TREE_CHAIN (prev) = TREE_CHAIN (x);
else
current_binding_level->incomplete_list = TREE_CHAIN (x);
}
else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
&& 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));
if (TREE_CODE (decl) != TYPE_DECL)
{
layout_decl (decl, 0);
if (compiling_objc)
objc_check_decl (decl);
rest_of_decl_compilation (decl, NULL, toplevel, 0);
if (! toplevel)
expand_decl (decl);
}
if (prev)
TREE_CHAIN (prev) = TREE_CHAIN (x);
else
current_binding_level->incomplete_list = TREE_CHAIN (x);
}
}
}
}
rest_of_type_compilation (t, toplevel);
return t;
}
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);
}
tree
start_enum (name)
tree name;
{
tree enumtype = 0;
if (name != 0)
enumtype = lookup_tag (ENUMERAL_TYPE, name, current_binding_level, 1);
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)
{
error ("redeclaration of `enum %s'", IDENTIFIER_POINTER (name));
TYPE_VALUES (enumtype) = 0;
}
enum_next_value = integer_zero_node;
enum_overflow = 0;
if (flag_short_enums)
TYPE_PACKED (enumtype) = 1;
return enumtype;
}
tree
finish_enum (enumtype, values, attributes)
tree enumtype;
tree values;
tree attributes;
{
tree pair, tem;
tree minnode = 0, maxnode = 0, enum_value_type;
int precision, unsign;
int toplevel = (global_binding_level == current_binding_level);
if (in_parm_level_p ())
warning ("enum defined inside parms");
decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
if (values == error_mark_node)
minnode = maxnode = integer_zero_node;
else
{
minnode = maxnode = TREE_VALUE (values);
for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
{
tree value = TREE_VALUE (pair);
if (tree_int_cst_lt (maxnode, value))
maxnode = value;
if (tree_int_cst_lt (value, minnode))
minnode = value;
}
}
unsign = (tree_int_cst_sgn (minnode) >= 0);
precision = MAX (min_precision (minnode, unsign),
min_precision (maxnode, unsign));
if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
{
tree narrowest = type_for_size (precision, unsign);
if (narrowest == 0)
{
warning ("enumeration values exceed range of largest integer");
narrowest = long_long_integer_type_node;
}
precision = TYPE_PRECISION (narrowest);
}
else
precision = TYPE_PRECISION (integer_type_node);
if (precision == TYPE_PRECISION (integer_type_node))
enum_value_type = type_for_size (precision, 0);
else
enum_value_type = enumtype;
TYPE_MIN_VALUE (enumtype) = minnode;
TYPE_MAX_VALUE (enumtype) = maxnode;
TYPE_PRECISION (enumtype) = precision;
TREE_UNSIGNED (enumtype) = unsign;
TYPE_SIZE (enumtype) = 0;
layout_type (enumtype);
if (values != error_mark_node)
{
for (pair = values; pair; pair = TREE_CHAIN (pair))
{
tree enu = TREE_PURPOSE (pair);
TREE_TYPE (enu) = enumtype;
DECL_SIZE (enu) = TYPE_SIZE (enumtype);
DECL_SIZE_UNIT (enu) = TYPE_SIZE_UNIT (enumtype);
DECL_ALIGN (enu) = TYPE_ALIGN (enumtype);
DECL_USER_ALIGN (enu) = TYPE_USER_ALIGN (enumtype);
DECL_MODE (enu) = TYPE_MODE (enumtype);
if (int_fits_type_p (DECL_INITIAL (enu), enum_value_type))
DECL_INITIAL (enu) = convert (enum_value_type, DECL_INITIAL (enu));
else
DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu));
TREE_PURPOSE (pair) = DECL_NAME (enu);
TREE_VALUE (pair) = DECL_INITIAL (enu);
}
TYPE_VALUES (enumtype) = values;
}
for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
{
if (tem == enumtype)
continue;
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);
TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
}
rest_of_type_compilation (enumtype, toplevel);
return enumtype;
}
tree
build_enumerator (name, value)
tree name, value;
{
tree decl, type;
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;
}
}
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 ("ISO C restricts enumerator values to range of `int'");
value = convert (integer_type_node, value);
}
enum_next_value = build_binary_op (PLUS_EXPR, value, integer_one_node, 0);
enum_overflow = tree_int_cst_lt (enum_next_value, value);
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) = convert (type, value);
pushdecl (decl);
if (flag_gen_index)
gen_indexing_info (INDEX_ENUM, IDENTIFIER_POINTER (name), lineno);
return tree_cons (decl, value, NULL_TREE);
}
int
start_function (declspecs, declarator, attributes)
tree declarator, declspecs, attributes;
{
tree decl1, old_decl;
tree restype;
int old_immediate_size_expand = immediate_size_expand;
current_function_returns_value = 0;
current_function_returns_null = 0;
current_function_returns_abnormally = 0;
warn_about_return_type = 0;
current_extern_inline = 0;
c_function_varargs = 0;
named_labels = 0;
shadowed_labels = 0;
immediate_size_expand = 0;
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1);
if (decl1 == 0)
{
immediate_size_expand = old_immediate_size_expand;
return 0;
}
decl_attributes (&decl1, attributes, (int)ATTR_FLAG_FUNCTION_DEF);
if (current_binding_level == global_binding_level)
maybe_apply_pragma_weak (decl1);
if (DECL_DECLARED_INLINE_P (decl1)
&& DECL_UNINLINABLE (decl1)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
warning_with_decl (decl1,
"inline function `%s' given attribute noinline");
announce_function (decl1);
if (flag_gen_index)
{
const char *name;
name = IDENTIFIER_POINTER (DECL_NAME (decl1));
if (name[1] != '[')
gen_indexing_info (INDEX_FUNCTION_BEGIN, name, lineno);
}
#ifdef PFE
if (pfe_operation == PFE_DUMP)
if (TREE_PUBLIC (decl1) || !DECL_INLINE (decl1))
error ("only static inline functions are allowed in the dump file");
#endif
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1))))
{
error ("return type is an incomplete type");
TREE_TYPE (decl1)
= build_function_type (void_type_node,
TYPE_ARG_TYPES (TREE_TYPE (decl1)));
}
if (warn_about_return_type)
pedwarn_c99 ("return type defaults to `int'");
current_function_parms = last_function_parms;
current_function_parm_tags = last_function_parm_tags;
DECL_INITIAL (decl1) = error_mark_node;
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 (old_decl == 0)
old_decl = IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1));
if (warn_strict_prototypes
&& TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0
&& !(old_decl != 0
&& (TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0
|| (DECL_BUILT_IN (old_decl)
&& ! C_DECL_ANTICIPATED (old_decl)))))
warning ("function declaration isn't a prototype");
else if (warn_missing_prototypes
&& TREE_PUBLIC (decl1)
&& !(old_decl != 0
&& (TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0
|| (DECL_BUILT_IN (old_decl)
&& ! C_DECL_ANTICIPATED (old_decl))))
&& ! MAIN_NAME_P (DECL_NAME (decl1)))
warning_with_decl (decl1, "no previous prototype for `%s'");
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");
else if (warn_missing_declarations
&& TREE_PUBLIC (decl1)
&& old_decl == 0
&& ! MAIN_NAME_P (DECL_NAME (decl1)))
warning_with_decl (decl1, "no previous declaration for `%s'");
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");
DECL_EXTERNAL (decl1) = current_extern_inline;
TREE_STATIC (decl1) = 1;
if (current_function_decl != 0)
TREE_PUBLIC (decl1) = 0;
if (warn_main > 0 && MAIN_NAME_P (DECL_NAME (decl1)))
{
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;
}
}
if (argct > 0 && (argct < 2 || argct > 3))
pedwarn_with_decl (decl1, "`%s' takes only zero or two arguments");
if (! TREE_PUBLIC (decl1))
pedwarn_with_decl (decl1, "`%s' is normally a non-static function");
}
current_function_decl = pushdecl (decl1);
pushlevel (0);
declare_parm_level (1);
current_binding_level->subblocks_tag_transparent = 1;
make_decl_rtl (current_function_decl, NULL);
restype = TREE_TYPE (TREE_TYPE (current_function_decl));
if (c_promoting_integer_type_p (restype))
{
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 (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl)))
TREE_ADDRESSABLE (current_function_decl) = 1;
immediate_size_expand = old_immediate_size_expand;
start_fname_decls ();
return 1;
}
void
c_mark_varargs ()
{
c_function_varargs = 1;
}
void
store_parm_decls ()
{
tree fndecl = current_function_decl;
tree parm;
tree specparms = current_function_parms;
tree parmtags = current_function_parm_tags;
tree parmdecls = getdecls ();
tree nonparms = 0;
tree context = decl_function_context (fndecl);
int prototype = 0;
int saved_warn_shadow = warn_shadow;
warn_shadow = 0;
if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST)
{
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");
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 (TREE_CODE (TREE_TYPE (parm)) != ERROR_MARK
&& VOID_TYPE_P (TREE_TYPE (parm)))
{
error_with_decl (parm, "parameter `%s' declared void");
TREE_TYPE (parm) = error_mark_node;
}
pushdecl (parm);
}
else
{
TREE_CHAIN (parm) = 0;
others = chainon (others, parm);
}
}
DECL_ARGUMENTS (fndecl) = getdecls ();
#if 0
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);
TREE_TYPE (dummy) = integer_type_node;
DECL_ARG_TYPE (dummy) = integer_type_node;
DECL_ARGUMENTS (fndecl) = chainon (DECL_ARGUMENTS (fndecl), dummy);
}
#endif
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
{
for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
DECL_WEAK (parm) = 0;
for (parm = specparms; parm; parm = TREE_CHAIN (parm))
{
tree tail, found = NULL;
if (TREE_VALUE (parm) == 0)
{
error_with_decl (fndecl,
"parameter name missing from parameter list");
TREE_PURPOSE (parm) = 0;
continue;
}
for (tail = parmdecls; tail; tail = TREE_CHAIN (tail))
if (DECL_NAME (tail) == TREE_VALUE (parm)
&& TREE_CODE (tail) == PARM_DECL)
{
found = tail;
break;
}
if (found && DECL_WEAK (found))
{
error_with_decl (found, "multiple parameters named `%s'");
found = 0;
}
if (found && VOID_TYPE_P (TREE_TYPE (found)))
{
error_with_decl (found, "parameter `%s' declared void");
TREE_TYPE (found) = integer_type_node;
DECL_ARG_TYPE (found) = integer_type_node;
layout_decl (found, 0);
}
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 (!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 (flag_isoc99)
pedwarn_with_decl (found, "type of `%s' defaults to `int'");
else if (extra_warnings)
warning_with_decl (found, "type of `%s' defaults to `int'");
pushdecl (found);
}
TREE_PURPOSE (parm) = found;
DECL_WEAK (found) = 1;
}
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
{
if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
{
error_with_decl (parm, "parameter `%s' has incomplete type");
TREE_TYPE (parm) = error_mark_node;
}
if (! DECL_WEAK (parm))
{
error_with_decl (parm,
"declaration for parameter `%s' but no such parameter");
specparms
= chainon (specparms,
tree_cons (parm, NULL_TREE, NULL_TREE));
}
}
parm = next;
}
parm = specparms;
DECL_ARGUMENTS (fndecl) = 0;
{
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 (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
{
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;
}
if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
TYPE_MAIN_VARIANT (TREE_VALUE (type))))
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
== TYPE_MAIN_VARIANT (TREE_VALUE (type)))
{
DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
if (PROMOTE_PROTOTYPES
&& INTEGRAL_TYPE_P (TREE_TYPE (parm))
&& TYPE_PRECISION (TREE_TYPE (parm))
< TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (parm) = integer_type_node;
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");
}
}
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;
}
else
{
tree actual = 0, last = 0, type;
for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
{
type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
if (last)
TREE_CHAIN (last) = type;
else
actual = type;
last = type;
}
type = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
if (last)
TREE_CHAIN (last) = type;
else
actual = type;
TREE_TYPE (fndecl) = build_type_copy (TREE_TYPE (fndecl));
TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = actual;
}
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
}
keep_next_if_subblocks = 1;
#if 0
keep_next_level_flag = 1;
#endif
gen_aux_info_record (fndecl, 1, 0, prototype);
init_function_start (fndecl, input_filename, lineno);
begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
if (context)
{
tree t;
DECL_LANG_SPECIFIC (fndecl)->pending_sizes
= nreverse (get_pending_sizes ());
for (t = DECL_LANG_SPECIFIC (fndecl)->pending_sizes;
t;
t = TREE_CHAIN (t))
SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = context;
}
cfun->x_whole_function_mode_p = 1;
immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1;
warn_shadow = saved_warn_shadow;
}
void
finish_function (nested, can_defer_p)
int nested;
int can_defer_p;
{
tree fndecl = current_function_decl;
#if 0
TREE_READONLY (fndecl) = 1;
#endif
poplevel (1, 0, 1);
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
if (flag_traditional && current_function_calls_setjmp)
{
setjmp_protect (DECL_INITIAL (fndecl));
setjmp_protect_args ();
}
if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted)
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
!= integer_type_node)
{
if (! warn_main)
pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
}
else
{
#ifdef DEFAULT_MAIN_RETURN
DEFAULT_MAIN_RETURN;
#else
if (flag_isoc99)
c_expand_return (integer_zero_node);
#endif
}
}
if (flag_gen_index)
{
const char *name;
name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
gen_indexing_info (INDEX_FUNCTION_END, NULL, lineno);
}
finish_fname_decls ();
finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
if (warn_return_type
&& TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
&& !current_function_returns_value && !current_function_returns_null
&& !current_function_returns_abnormally
&& !MAIN_NAME_P (DECL_NAME (fndecl))
&& !C_FUNCTION_IMPLICIT_INT (fndecl)
&& DECL_INLINE (fndecl))
warning ("no return statement in function returning non-void");
free_after_parsing (cfun);
free_after_compilation (cfun);
cfun = NULL;
if (! nested)
{
c_expand_body (fndecl, nested, can_defer_p);
current_function_decl = NULL;
}
}
void
c_expand_deferred_function (fndecl)
tree fndecl;
{
if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl))
{
c_expand_body (fndecl, 0, 0);
current_function_decl = NULL;
}
}
static void
c_expand_body (fndecl, nested_p, can_defer_p)
tree fndecl;
int nested_p, can_defer_p;
{
int uninlinable = 1;
if (flag_syntax_only)
return;
if (flag_inline_trees)
{
timevar_push (TV_INTEGRATION);
uninlinable = ! tree_inlinable_function_p (fndecl);
if (! uninlinable && can_defer_p
&& defer_fn (fndecl))
{
(*debug_hooks->deferred_inline_function) (fndecl);
timevar_pop (TV_INTEGRATION);
return;
}
optimize_inline_calls (fndecl);
timevar_pop (TV_INTEGRATION);
}
timevar_push (TV_EXPAND);
if (nested_p)
{
expand_pending_sizes (DECL_LANG_SPECIFIC (fndecl)->pending_sizes);
push_function_context ();
}
current_function_decl = fndecl;
input_filename = DECL_SOURCE_FILE (fndecl);
init_function_start (fndecl, input_filename, DECL_SOURCE_LINE (fndecl));
cfun->x_whole_function_mode_p = 1;
immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1;
if (c_function_varargs)
mark_varargs ();
expand_function_start (fndecl, 0);
if (DECL_NAME (fndecl)
&& MAIN_NAME_P (DECL_NAME (fndecl))
&& DECL_CONTEXT (fndecl) == NULL_TREE)
expand_main_function ();
expand_stmt (DECL_SAVED_TREE (fndecl));
if (uninlinable)
{
DECL_SAVED_TREE (fndecl) = NULL_TREE;
}
immediate_size_expand = 1;
if (lang_expand_function_end)
(*lang_expand_function_end) ();
expand_function_end (input_filename, lineno, 0);
if (nested_p)
ggc_push_context ();
rest_of_compilation (fndecl);
if (nested_p)
ggc_pop_context ();
if (extra_warnings
&& current_function_returns_value
&& current_function_returns_null)
warning ("this function may return with or without a value");
if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
{
tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
if (ret_type && TYPE_SIZE_UNIT (ret_type)
&& TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
&& 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
larger_than_size))
{
unsigned int size_as_int
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
warning_with_decl (fndecl,
"size of return value of `%s' is %u bytes",
size_as_int);
else
warning_with_decl (fndecl,
"size of return value of `%s' is larger than %d bytes",
larger_than_size);
}
}
if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested_p
&& ! flag_inline_trees)
{
if (DECL_INITIAL (fndecl) != 0)
DECL_INITIAL (fndecl) = error_mark_node;
DECL_ARGUMENTS (fndecl) = 0;
}
if (DECL_STATIC_CONSTRUCTOR (fndecl))
{
if (targetm.have_ctors_dtors)
(* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
DEFAULT_INIT_PRIORITY);
else
static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
}
if (DECL_STATIC_DESTRUCTOR (fndecl))
{
if (targetm.have_ctors_dtors)
(* targetm.asm_out.destructor) (XEXP (DECL_RTL (fndecl), 0),
DEFAULT_INIT_PRIORITY);
else
static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
}
if (nested_p)
pop_function_context ();
timevar_pop (TV_EXPAND);
}
void
check_for_loop_decls ()
{
tree t;
if (!flag_isoc99)
{
error ("`for' loop initial declaration used outside C99 mode");
return;
}
for (t = gettags (); t; t = TREE_CHAIN (t))
{
if (TREE_PURPOSE (t) != 0)
{
enum tree_code code = TREE_CODE (TREE_VALUE (t));
if (code == RECORD_TYPE)
error ("`struct %s' declared in `for' loop initial declaration",
IDENTIFIER_POINTER (TREE_PURPOSE (t)));
else if (code == UNION_TYPE)
error ("`union %s' declared in `for' loop initial declaration",
IDENTIFIER_POINTER (TREE_PURPOSE (t)));
else
error ("`enum %s' declared in `for' loop initial declaration",
IDENTIFIER_POINTER (TREE_PURPOSE (t)));
}
}
for (t = getdecls (); t; t = TREE_CHAIN (t))
{
if (TREE_CODE (t) != VAR_DECL && DECL_NAME (t))
error_with_decl (t, "declaration of non-variable `%s' in `for' loop initial declaration");
else if (TREE_STATIC (t))
error_with_decl (t, "declaration of static variable `%s' in `for' loop initial declaration");
else if (DECL_EXTERNAL (t))
error_with_decl (t, "declaration of `extern' variable `%s' in `for' loop initial declaration");
}
}
struct c_language_function
{
struct language_function base;
tree named_labels;
tree shadowed_labels;
int returns_value;
int returns_null;
int returns_abnormally;
int warn_about_return_type;
int extern_inline;
struct binding_level *binding_level;
};
void
push_c_function_context (f)
struct function *f;
{
struct c_language_function *p;
p = ((struct c_language_function *)
xmalloc (sizeof (struct c_language_function)));
f->language = (struct language_function *) p;
p->base.x_stmt_tree = c_stmt_tree;
p->base.x_scope_stmt_stack = c_scope_stmt_stack;
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->returns_abnormally = current_function_returns_abnormally;
p->warn_about_return_type = warn_about_return_type;
p->extern_inline = current_extern_inline;
p->binding_level = current_binding_level;
}
void
pop_c_function_context (f)
struct function *f;
{
struct c_language_function *p
= (struct c_language_function *) f->language;
tree link;
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
&& DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
{
DECL_INITIAL (current_function_decl) = error_mark_node;
DECL_ARGUMENTS (current_function_decl) = 0;
}
c_stmt_tree = p->base.x_stmt_tree;
c_scope_stmt_stack = p->base.x_scope_stmt_stack;
named_labels = p->named_labels;
shadowed_labels = p->shadowed_labels;
current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null;
current_function_returns_abnormally = p->returns_abnormally;
warn_about_return_type = p->warn_about_return_type;
current_extern_inline = p->extern_inline;
current_binding_level = p->binding_level;
free (p);
f->language = 0;
}
void
mark_c_function_context (f)
struct function *f;
{
struct c_language_function *p
= (struct c_language_function *) f->language;
if (p == 0)
return;
mark_c_language_function (&p->base);
ggc_mark_tree (p->shadowed_labels);
ggc_mark_tree (p->named_labels);
mark_binding_level (&p->binding_level);
}
void
copy_lang_decl (decl)
tree decl;
{
struct lang_decl *ld;
if (!DECL_LANG_SPECIFIC (decl))
return;
ld = (struct lang_decl *) GGC_ALLOC (sizeof (struct lang_decl),
PFE_ALLOC_GGC_LANG_DECL);
memcpy ((char *) ld, (char *) DECL_LANG_SPECIFIC (decl),
sizeof (struct lang_decl));
DECL_LANG_SPECIFIC (decl) = ld;
}
void
lang_mark_tree (t)
tree t;
{
if (TREE_CODE (t) == IDENTIFIER_NODE)
{
struct lang_identifier *i = (struct lang_identifier *) t;
ggc_mark_tree (i->global_value);
ggc_mark_tree (i->local_value);
ggc_mark_tree (i->label_value);
ggc_mark_tree (i->implicit_decl);
ggc_mark_tree (i->error_locus);
ggc_mark_tree (i->limbo_value);
}
else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
ggc_mark (TYPE_LANG_SPECIFIC (t));
else if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
{
ggc_mark (DECL_LANG_SPECIFIC (t));
c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base);
ggc_mark_tree (DECL_LANG_SPECIFIC (t)->pending_sizes);
}
}
int
stmts_are_full_exprs_p ()
{
return 0;
}
stmt_tree
current_stmt_tree ()
{
return &c_stmt_tree;
}
tree *
current_scope_stmt_stack ()
{
return &c_scope_stmt_stack;
}
int
anon_aggr_type_p (node)
tree node ATTRIBUTE_UNUSED;
{
return 0;
}
void
extract_interface_info ()
{
}
tree
c_begin_compound_stmt ()
{
tree stmt;
stmt = add_stmt (build_stmt (COMPOUND_STMT, NULL_TREE));
return stmt;
}
void
c_expand_decl_stmt (t)
tree t;
{
tree decl = DECL_STMT_DECL (t);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_CONTEXT (decl) == current_function_decl
&& DECL_SAVED_TREE (decl))
c_expand_body (decl, 1, 0);
}
tree
identifier_global_value (t)
tree t;
{
return IDENTIFIER_GLOBAL_VALUE (t);
}
void
record_builtin_type (rid_index, name, type)
enum rid rid_index;
const char *name;
tree type;
{
tree id;
if (name == 0)
id = ridpointers[(int) rid_index];
else
id = get_identifier (name);
pushdecl (build_decl (TYPE_DECL, id, type));
}
tree
build_void_list_node ()
{
tree t = build_tree_list (NULL_TREE, void_type_node);
return t;
}
#ifdef PFE
void
pfe_c_init_decl_processing ()
{
if (pfe_operation != PFE_LOAD)
return;
c_parse_init ();
global_binding_level->level_chain = current_binding_level;
current_binding_level = global_binding_level;
global_binding_level->keep = keep_next_level_flag;
keep_next_level_flag = 0;
global_binding_level->keep_if_subblocks = keep_next_if_subblocks;
keep_next_if_subblocks = 0;
pfe_c_common_nodes_and_builtins ();
lang_type_promotes_to = simple_type_promotes_to;
pedantic_lvalues = pedantic;
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
#ifdef ENABLE_DMP_TREE
c_prev_lang_dump_tree_p = set_dump_tree_p (c_dump_tree_p);
SET_MAX_DMP_TREE_CODE(LAST_C_TREE_CODE);
#endif
ggc_add_tree_root (c_global_trees, CTI_MAX);
ggc_add_root (&c_stmt_tree, 1, sizeof c_stmt_tree, mark_stmt_tree);
ggc_add_tree_root (&c_scope_stmt_stack, 1);
ggc_add_tree_root (&named_labels, 1);
ggc_add_tree_root (&shadowed_labels, 1);
ggc_add_root (¤t_binding_level, 1, sizeof current_binding_level,
mark_binding_level);
ggc_add_root (&label_level_chain, 1, sizeof label_level_chain,
mark_binding_level);
ggc_add_tree_root (&static_ctors, 1);
ggc_add_tree_root (&static_dtors, 1);
}
void
pfe_freeze_thaw_binding_level (pp)
struct binding_level **pp;
{
struct binding_level *p;
if (pp == NULL)
{
if (PFE_FREEZING)
{
pfe_compiler_state_ptr->global_binding_level = global_binding_level;
p = PFE_FREEZE_THAW_PTR (&pfe_compiler_state_ptr->global_binding_level);
}
else
{
p = PFE_FREEZE_THAW_PTR (&pfe_compiler_state_ptr->global_binding_level);
global_binding_level = pfe_compiler_state_ptr->global_binding_level;
}
}
else
p = PFE_FREEZE_THAW_PTR (pp);
while (p)
{
PFE_FREEZE_THAW_WALK (p->names);
PFE_FREEZE_THAW_WALK (p->tags);
PFE_FREEZE_THAW_WALK (p->shadowed);
PFE_FREEZE_THAW_WALK (p->blocks);
PFE_FREEZE_THAW_WALK (p->this_block);
PFE_FREEZE_THAW_WALK (p->incomplete_list);
PFE_FREEZE_THAW_WALK (p->parm_order);
p = PFE_FREEZE_THAW_PTR (&p->level_chain);
}
}
void
pfe_freeze_thaw_language_function (pp)
struct language_function **pp;
{
struct c_language_function *p;
p = (struct c_language_function *)PFE_FREEZE_THAW_PTR (pp);
if (!p)
return;
pfe_freeze_thaw_common_language_function (&p->base);
PFE_FREEZE_THAW_WALK (p->named_labels);
PFE_FREEZE_THAW_WALK (p->shadowed_labels);
pfe_freeze_thaw_binding_level (&p->binding_level);
}
void
pfe_setdecls (names)
tree names;
{
current_binding_level->names = names;
}
DEFINE_CHECK_STRUCT_FUNCTION (c_language_function)
DEFINE_CHECK_STRUCT_FUNCTION (binding_level)
#endif