/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+ Free Software Foundation, Inc.
This file is part of GNU CC.
#include "config.h"
#include "system.h"
+#include "intl.h"
#include "tree.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 "defaults.h"
#include "ggc.h"
+#include "tm_p.h"
#if USE_CPPLIB
#include "cpplib.h"
#ifndef WCHAR_TYPE
#define WCHAR_TYPE "int"
#endif
+
+#ifndef WINT_TYPE
+#define WINT_TYPE "unsigned int"
+#endif
\f
/* Do GC. */
int ggc_p = 1;
tree pending_invalid_xref;
/* File and line to appear in the eventual error message. */
-char *pending_invalid_xref_file;
+const char *pending_invalid_xref_file;
int pending_invalid_xref_line;
/* While defining an enum type, this is 1 plus the last enumerator
/* Similar, for the file and line that the prototype came from if this is
an old-style definition. */
-static char *current_function_prototype_file;
+static const char *current_function_prototype_file;
static int current_function_prototype_line;
/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
static int c_function_varargs;
-/* The FUNCTION_DECL for the function currently being compiled,
- or 0 if between functions. */
-tree current_function_decl;
-
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
/* Forward declarations. */
-static struct binding_level * make_binding_level PROTO((void));
-static void mark_binding_level PROTO((void *));
-static void clear_limbo_values PROTO((tree));
-static int duplicate_decls PROTO((tree, tree, int));
-static int redeclaration_error_message PROTO((tree, tree));
-static void storedecls PROTO((tree));
-static void storetags PROTO((tree));
-static tree lookup_tag PROTO((enum tree_code, tree,
- struct binding_level *, int));
-static tree lookup_tag_reverse PROTO((tree));
-static tree grokdeclarator PROTO((tree, tree, enum decl_context,
- int));
-static tree grokparms PROTO((tree, int));
-static void layout_array_type PROTO((tree));
+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, const char *, int));
\f
/* C-specific option variables. */
int flag_traditional;
-/* Nonzero means use the ISO C9x dialect of C. */
+/* Nonzero means enable C89 Amendment 1 features, other than digraphs. */
+
+int flag_isoc94 = 0;
-int flag_isoc9x = 0;
+/* Nonzero means use the ISO C99 dialect of C. */
+
+int flag_isoc99 = 0;
+
+/* Nonzero means accept digraphs. */
+
+int flag_digraphs = 1;
/* Nonzero means that we have builtin functions, and main is an int */
/* Nonzero means message about use of implicit function declarations;
1 means warning; 2 means error. */
-int mesg_implicit_function_declaration;
+int mesg_implicit_function_declaration = -1;
/* Nonzero means give string constants the type `const char *'
to get extra warnings from them. These warnings will be too numerous
int warn_multichar = 1;
+/* Wrapper since C and C++ expand_expr_stmt are different. */
+
+expand_expr_stmt_fn lang_expand_expr_stmt = c_expand_expr_stmt;
+
+/* The variant of the C language being processed. */
+
+c_language_kind c_language = clk_c;
+
/* Nonzero means `$' can be in an identifier. */
#ifndef DOLLARS_IN_IDENTIFIERS
{
flag_traditional = 1;
flag_writable_strings = 1;
+ flag_digraphs = 0;
}
else if (!strcmp (p, "-fallow-single-precision"))
flag_allow_single_precision = 1;
{
flag_traditional = 0;
flag_writable_strings = 0;
+ flag_digraphs = 1;
}
else if (!strncmp (p, "-std=", 5))
{
recognize:
-std=iso9899:1990 same as -ansi
-std=iso9899:199409 ISO C as modified in amend. 1
- -std=iso9899:199x ISO C 9x
+ -std=iso9899:1999 ISO C 99
-std=c89 same as -std=iso9899:1990
- -std=c9x same as -std=iso9899:199x
+ -std=c99 same as -std=iso9899:1999
-std=gnu89 default, iso9899:1990 + gnu extensions
- -std=gnu9x iso9899:199x + gnu extensions
+ -std=gnu99 iso9899:1999 + gnu extensions
*/
const char *argstart = &p[5];
|| !strcmp (argstart, "c89"))
{
iso_1990:
+ flag_digraphs = 0;
+ flag_isoc94 = 0;
+ iso_1990_digraphs:
flag_traditional = 0;
flag_writable_strings = 0;
flag_no_asm = 1;
flag_no_nonansi_builtin = 1;
- flag_isoc9x = 0;
+ flag_isoc99 = 0;
}
else if (!strcmp (argstart, "iso9899:199409"))
{
- /* ??? The changes since ISO C 1990 are not supported. */
- goto iso_1990;
+ flag_digraphs = 1;
+ flag_isoc94 = 1;
+ goto iso_1990_digraphs;
}
else if (!strcmp (argstart, "iso9899:199x")
- || !strcmp (argstart, "c9x"))
+ || !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_isoc9x = 1;
+ flag_isoc99 = 1;
+ flag_digraphs = 1;
+ flag_isoc94 = 1;
}
else if (!strcmp (argstart, "gnu89"))
{
flag_writable_strings = 0;
flag_no_asm = 0;
flag_no_nonansi_builtin = 0;
- flag_isoc9x = 0;
+ flag_isoc99 = 0;
+ flag_digraphs = 1;
+ flag_isoc94 = 0;
}
- else if (!strcmp (argstart, "gnu9x"))
+ 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_isoc9x = 1;
+ flag_isoc99 = 1;
+ flag_digraphs = 1;
+ flag_isoc94 = 1;
}
else
error ("unknown C standard `%s'", argstart);
warn_traditional = 1;
else if (!strcmp (p, "-Wno-traditional"))
warn_traditional = 0;
+ else if (!strncmp (p, "-Wformat=", 9))
+ warn_format = atol (p + 9);
else if (!strcmp (p, "-Wformat"))
warn_format = 1;
else if (!strcmp (p, "-Wno-format"))
warn_implicit_int = 1;
mesg_implicit_function_declaration = 1;
warn_return_type = 1;
- warn_unused = 1;
+ set_Wunused (1);
warn_switch = 1;
warn_format = 1;
warn_char_subscripts = 1;
#if 0
/* Warn about incomplete structure types in this level. */
for (link = tags; link; link = TREE_CHAIN (link))
- if (TYPE_SIZE (TREE_VALUE (link)) == 0)
+ if (!COMPLETE_TYPE_P (TREE_VALUE (link)))
{
tree type = TREE_VALUE (link);
tree type_name = TYPE_NAME (type);
define_label (input_filename, lineno,
DECL_NAME (label));
}
- else if (warn_unused && !TREE_USED (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;
define_label (input_filename, lineno,
DECL_NAME (TREE_VALUE (link)));
}
- else if (warn_unused && !TREE_USED (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;
TYPE_NAME (type) = name;
}
- if (b == global_binding_level)
- b->tags = perm_tree_cons (name, type, b->tags);
- else
- b->tags = saveable_tree_cons (name, type, b->tags);
+ b->tags = tree_cons (name, type, b->tags);
/* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
tagged type we just added to the current binding level. This fake
tree newtype = TREE_TYPE (newdecl);
int errmsg = 0;
- if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
+ if (DECL_P (olddecl))
DECL_MACHINE_ATTRIBUTES (newdecl)
= merge_machine_decl_attributes (olddecl, newdecl);
tree oldreturntype = TREE_TYPE (oldtype);
tree newreturntype = TREE_TYPE (newtype);
- /* Make sure we put the new type in the same obstack as the old ones.
- If the old types are not both in the same obstack, use the
- permanent one. */
- if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
- push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
- else
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- }
-
if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
{
/* Function types may be shared, so we can't just modify
}
if (! different_binding_level)
TREE_TYPE (olddecl) = oldtype;
-
- pop_obstacks ();
}
if (!types_match)
{
different_binding_level is true. */
tree write_olddecl = different_binding_level ? newdecl : olddecl;
- /* Make sure we put the new type in the same obstack as the old ones.
- If the old types are not both in the same obstack, use the permanent
- one. */
- if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
- push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
- else
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- }
-
/* Merge the data types specified in the two decls. */
if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
{
{
/* Since the type is OLDDECL's, make OLDDECL's size go with. */
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_ALIGN (newdecl) = DECL_ALIGN (olddecl);
+ DECL_USER_ALIGN (newdecl) |= DECL_ALIGN (olddecl);
+ }
}
/* Keep the old rtl since we can safely use it. */
DECL_RTL (newdecl) = DECL_RTL (olddecl);
/* Merge the type qualifiers. */
- if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
- && !TREE_THIS_VOLATILE (newdecl))
+ 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)
+ if (TREE_CODE (newdecl) == VAR_DECL
+ /* If an automatic variable is re-declared in the same
+ function scope, but the old declaration was not
+ volatile, make_var_volatile() would crash because the
+ variable would have been assigned to a pseudo, not a
+ MEM. Since this duplicate declaration is invalid
+ anyway, we just skip the call. */
+ && errmsg == 0)
make_var_volatile (newdecl);
}
DECL_NO_LIMIT_STACK (newdecl)
|= DECL_NO_LIMIT_STACK (olddecl);
}
-
- pop_obstacks ();
}
/* If cannot merge, then use the new type and qualifiers,
and don't preserve the old rtl. */
TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
}
- /* If either decl says `inline', this fn is inline,
- unless its definition was passed already. */
- if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
- DECL_INLINE (olddecl) = 1;
- DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
-
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
+ /* If either decl says `inline', this fn is inline,
+ unless its definition was passed already. */
+ if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
+ DECL_INLINE (olddecl) = 1;
+
+ DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+
if (DECL_BUILT_IN (olddecl))
{
/* Get rid of any built-in function if new arg types don't match it
DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
if (DECL_INLINE (newdecl))
- DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ORIGIN (olddecl);
+ DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ABSTRACT_ORIGIN (olddecl);
}
}
if (different_binding_level)
if (name)
{
- char *file;
+ const char *file;
int line;
int different_binding_level = 0;
DECL_ORIGINAL_TYPE (x) = tt;
tt = build_type_copy (tt);
TYPE_NAME (tt) = x;
+ TREE_USED (tt) = TREE_USED (x);
TREE_TYPE (x) = tt;
}
}
We get warnings about inline functions where they are defined.
Avoid duplicate warnings where they are used. */
- if (TREE_PUBLIC (x) && ! DECL_INLINE (x))
+ if (TREE_PUBLIC (x)
+ && ! (TREE_CODE (x) == FUNCTION_DECL && DECL_INLINE (x)))
{
tree decl;
{
if (type == error_mark_node)
break;
- if (! TYPE_CONTEXT (type))
+ if (TYPE_CONTEXT (type))
{
warning_with_decl (x, "type of external `%s' is not global");
/* By exiting the loop early, we leave TYPE nonzero,
/* Here to install a non-global value. */
tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
+
IDENTIFIER_LOCAL_VALUE (name) = x;
/* If this is an extern function declaration, see if we
have a global definition or declaration for the function. */
if (oldlocal == 0
- && DECL_EXTERNAL (x) && !DECL_INLINE (x)
&& oldglobal != 0
&& TREE_CODE (x) == FUNCTION_DECL
- && TREE_CODE (oldglobal) == FUNCTION_DECL)
+ && TREE_CODE (oldglobal) == FUNCTION_DECL
+ && DECL_EXTERNAL (x) && ! DECL_INLINE (x))
{
/* We have one. Their types must agree. */
if (! comptypes (TREE_TYPE (x),
b->shadowed = tree_cons (name, oldlocal, b->shadowed);
}
- /* Keep count of variables in this level with incomplete type. */
- if (TYPE_SIZE (TREE_TYPE (x)) == 0)
+ /* Keep count of variables in this level with incomplete type.
+ If the input is erroneous, we can have error_mark in the type
+ slot (e.g. "f(void a, ...)") - that doesn't count as an
+ incomplete type. */
+ if (TREE_TYPE (x) != error_mark_node
+ && !COMPLETE_TYPE_P (TREE_TYPE (x)))
++b->n_incomplete;
}
/* Only one "implicit declaration" warning per identifier. */
int implicit_warning;
- /* Save the decl permanently so we can warn if definition follows. */
- push_obstacks_nochange ();
- end_temporary_allocation ();
-
/* We used to reuse an old implicit decl here,
but this loses with inline functions because it can clobber
the saved decl chains. */
rest_of_decl_compilation (decl, NULL_PTR, 0, 0);
- if (mesg_implicit_function_declaration && implicit_warning)
- {
- if (mesg_implicit_function_declaration == 2)
- error ("implicit declaration of function `%s'",
- IDENTIFIER_POINTER (functionid));
- else
- warning ("implicit declaration of function `%s'",
- IDENTIFIER_POINTER (functionid));
- }
+ 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);
- pop_obstacks ();
-
return decl;
}
+void
+implicit_decl_warning (id)
+ tree id;
+{
+ char *name = IDENTIFIER_POINTER (id);
+ 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);
+}
+
/* Return zero if the declaration NEWDECL is valid
when the declaration OLDDECL (assumed to be for the same name)
has already been seen.
if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0
/* However, defining once as extern inline and a second
time in another way is ok. */
- && !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
- && !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
+ && ! (DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
+ && ! (DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
return 1;
return 0;
}
tree
define_label (filename, line, name)
- char *filename;
+ const char *filename;
int line;
tree name;
{
decl = lookup_label (name);
}
+ if (warn_traditional && lookup_name (name))
+ warning ("traditional C lacks a separate namespace for labels, identifier `%s' conflicts",
+ IDENTIFIER_POINTER (name));
+
if (DECL_INITIAL (decl) != 0)
{
error ("duplicate label `%s'", IDENTIFIER_POINTER (name));
}
\f
/* Mark ARG for GC. */
+
static void
mark_binding_level (arg)
void *arg;
{
struct binding_level *level = *(struct binding_level **) arg;
- while (level)
+ for (; level != 0; level = level->level_chain)
{
ggc_mark_tree (level->names);
ggc_mark_tree (level->tags);
ggc_mark_tree (level->blocks);
ggc_mark_tree (level->this_block);
ggc_mark_tree (level->parm_order);
- level = level->level_chain;
}
}
tree ptr_ftype_void, ptr_ftype_ptr;
int wchar_type_size;
tree array_domain_type;
+ tree t;
current_function_decl = NULL;
named_labels = NULL;
Traditionally, use a signed type.
Note that stddef.h uses `unsigned long',
and this must agree, even if long and int are the same size. */
- set_sizetype
- (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
- if (flag_traditional && TREE_UNSIGNED (sizetype))
- set_sizetype (signed_type (sizetype));
+ t = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)));
+ signed_size_type_node = signed_type (t);
+ if (flag_traditional && TREE_UNSIGNED (t))
+ t = signed_type (t);
+
+ set_sizetype (t);
/* Create the widest literal types. */
- widest_integer_literal_type_node = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
- widest_unsigned_literal_type_node = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
+ widest_integer_literal_type_node
+ = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
+ widest_unsigned_literal_type_node
+ = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
pushdecl (build_decl (TYPE_DECL, NULL_TREE,
widest_integer_literal_type_node));
pushdecl (build_decl (TYPE_DECL, NULL_TREE,
signed_wchar_type_node = signed_type (wchar_type_node);
unsigned_wchar_type_node = unsigned_type (wchar_type_node);
+ wint_type_node = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WINT_TYPE)));
+
boolean_type_node = integer_type_node;
boolean_true_node = integer_one_node;
boolean_false_node = integer_zero_node;
array type. */
char_array_type_node
= build_array_type (char_type_node, array_domain_type);
+
/* Likewise for arrays of ints. */
int_array_type_node
= build_array_type (integer_type_node, array_domain_type);
+
/* This is for wide string constants. */
wchar_array_type_node
= build_array_type (wchar_type_node, array_domain_type);
= build_function_type (integer_type_node, NULL_TREE);
ptrdiff_type_node
= TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
+ unsigned_ptrdiff_type_node = unsigned_type (ptrdiff_type_node);
c_common_nodes_and_builtins (0, flag_no_builtin, flag_no_nonansi_builtin);
= build_function_type (ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node, endlink));
+ /* Types which are common to the fortran compiler and libf2c. When
+ changing these, you also need to be concerned with f/com.h. */
+
+ 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));
+ }
+
builtin_function ("__builtin_aggregate_incoming_address",
build_function_type (ptr_type_node, NULL_TREE),
BUILT_IN_AGGREGATE_INCOMING_ADDRESS,
pedantic_lvalues = pedantic;
/* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */
+ make_fname_decl = c_make_fname_decl;
declare_function_name ();
start_identifier_warnings ();
incomplete_decl_finalize_hook = finish_incomplete_decl;
- lang_get_alias_set = c_get_alias_set;
-
/* Record our roots. */
ggc_add_tree_root (c_global_trees, CTI_MAX);
- ggc_add_tree_root (¤t_function_decl, 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,
ggc_add_tree_root (&static_dtors, 1);
}
+/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
+ decl, NAME is the initialization string and TYPE_DEP indicates whether
+ NAME depended on the type of the function. As we don't yet implement
+ delayed emission of static data, we mark the decl as emitted
+ so it is not placed in the output. Anything using it must therefore pull
+ out the STRING_CST initializer directly. This does mean that these names
+ are string merging candidates, which C99 does not permit. */
+
+static tree
+c_make_fname_decl (id, name, type_dep)
+ tree id;
+ const char *name;
+ int type_dep ATTRIBUTE_UNUSED;
+{
+ 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 (build_int_2 (length, 0)));
+
+ decl = build_decl (VAR_DECL, id, type);
+ TREE_STATIC (decl) = 1;
+ TREE_READONLY (decl) = 1;
+ TREE_ASM_WRITTEN (decl) = 1;
+ DECL_SOURCE_LINE (decl) = 0;
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_IN_SYSTEM_HEADER (decl) = 1;
+ DECL_IGNORED_P (decl) = 1;
+ init = build_string (length + 1, name);
+ TREE_TYPE (init) = type;
+ DECL_INITIAL (decl) = init;
+ finish_decl (pushdecl (decl), init, NULL_TREE);
+
+ return decl;
+}
+
/* Return a definition for a builtin function named NAME and whose data type
is TYPE. TYPE should be a function type with argument types.
FUNCTION_CODE tells later passes how to compile calls to this function.
do go through here. Structure field declarations are done by
grokfield and not through here. */
-/* Set this to zero to debug not using the temporary obstack
- to parse initializers. */
-int debug_temp_inits = 1;
-
tree
start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
tree declarator, declspecs;
register tree decl = grokdeclarator (declarator, declspecs,
NORMAL, initialized);
register tree tem;
- int init_written = initialized;
-
- /* The corresponding pop_obstacks is in finish_decl. */
- push_obstacks_nochange ();
if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "main"))
default:
/* Don't allow initializations for incomplete types
except for arrays which might be completed by the initialization. */
- if (TYPE_SIZE (TREE_TYPE (decl)) != 0)
+ if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
{
/* A complete type is ok if size is fixed. */
IDENTIFIER_POINTER (DECL_NAME (decl)));
initialized = 0;
}
- else if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl))) == 0)
+ else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
{
error ("elements of array `%s' have incomplete type",
IDENTIFIER_POINTER (DECL_NAME (decl)));
(which may or may not happen). */
&& DECL_RTL (tem) == 0)
{
- if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
+ if (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);
}
- if (init_written)
- {
- /* When parsing and digesting the initializer,
- use temporary storage. Do this even if we will ignore the value. */
- if (current_binding_level == global_binding_level && debug_temp_inits)
- temporary_allocation ();
- }
-
return tem;
}
{
register tree type = TREE_TYPE (decl);
int was_incomplete = (DECL_SIZE (decl) == 0);
- int temporary = allocation_temporary_p ();
char *asmspec = 0;
/* If a name was specified, get the string. */
}
}
- /* Pop back to the obstack that is current for this binding level.
- This is because MAXINDEX, rtl, etc. to be made below
- must go in the permanent obstack. But don't discard the
- temporary data yet. */
- pop_obstacks ();
-#if 0 /* pop_obstacks was near the end; this is what was here. */
- if (current_binding_level == global_binding_level && temporary)
- end_temporary_allocation ();
-#endif
-
/* Deduce size of array from initialization, if not already known */
if (TREE_CODE (type) == ARRAY_TYPE
if (TREE_CODE (decl) == VAR_DECL)
{
- if (DECL_SIZE (decl) == 0
- && TYPE_SIZE (TREE_TYPE (decl)) != 0)
+ if (DECL_SIZE (decl) == 0 && COMPLETE_TYPE_P (TREE_TYPE (decl)))
layout_decl (decl, 0);
if (DECL_SIZE (decl) == 0
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
{
- if ((flag_traditional || TREE_PERMANENT (decl))
- && allocation_temporary_p ())
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- /* This is a no-op in c-lang.c or something real in objc-actions.c. */
- maybe_objc_check_decl (decl);
- rest_of_decl_compilation (decl, asmspec,
- (DECL_CONTEXT (decl) == 0
- || TREE_ASM_WRITTEN (decl)),
- 0);
- pop_obstacks ();
- }
- else
- {
- /* This is a no-op in c-lang.c or something real in objc-actions.c. */
- maybe_objc_check_decl (decl);
- rest_of_decl_compilation (decl, asmspec,
- (DECL_CONTEXT (decl) == 0
- || TREE_ASM_WRITTEN (decl)),
- 0);
- }
+ /* This is a no-op in c-lang.c or something real in objc-actions.c. */
+ maybe_objc_check_decl (decl);
+ rest_of_decl_compilation (decl, asmspec,
+ (DECL_CONTEXT (decl) == 0
+ || TREE_ASM_WRITTEN (decl)), 0);
+
if (DECL_CONTEXT (decl) != 0)
{
/* Recompute the RTL of a local array now
{
/* This is a no-op in c-lang.c or something real in objc-actions.c. */
maybe_objc_check_decl (decl);
- rest_of_decl_compilation (decl, NULL_PTR, DECL_CONTEXT (decl) == 0,
- 0);
- }
-
- /* ??? After 2.3, test (init != 0) instead of TREE_CODE. */
- /* This test used to include TREE_PERMANENT, however, we have the same
- problem with initializers at the function level. Such initializers get
- saved until the end of the function on the momentary_obstack. */
- if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
- && temporary
- /* DECL_INITIAL is not defined in PARM_DECLs, since it shares
- space with DECL_ARG_TYPE. */
- && TREE_CODE (decl) != PARM_DECL)
- {
- /* We need to remember that this array HAD an initialization,
- but discard the actual temporary nodes,
- since we can't have a permanent node keep pointing to them. */
- /* We make an exception for inline functions, since it's
- normal for a local extern redeclaration of an inline function
- to have a copy of the top-level decl's DECL_INLINE. */
- if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node)
- {
- /* If this is a const variable, then preserve the
- initializer instead of discarding it so that we can optimize
- references to it. */
- /* This test used to include TREE_STATIC, but this won't be set
- for function level initializers. */
- if (TREE_READONLY (decl) || ITERATOR_P (decl))
- {
- preserve_initializer ();
- /* Hack? Set the permanent bit for something that is permanent,
- but not on the permanent obstack, so as to convince
- output_constant_def to make its rtl on the permanent
- obstack. */
- TREE_PERMANENT (DECL_INITIAL (decl)) = 1;
-
- /* The initializer and DECL must have the same (or equivalent
- types), but if the initializer is a STRING_CST, its type
- might not be on the right obstack, so copy the type
- of DECL. */
- TREE_TYPE (DECL_INITIAL (decl)) = type;
- }
- else
- DECL_INITIAL (decl) = error_mark_node;
- }
- }
-
- /* If requested, warn about definitions of large data objects. */
-
- if (warn_larger_than
- && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
- && !DECL_EXTERNAL (decl))
- {
- register tree decl_size = DECL_SIZE (decl);
-
- if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
- {
- unsigned units = TREE_INT_CST_LOW(decl_size) / BITS_PER_UNIT;
-
- if (units > larger_than_size)
- warning_with_decl (decl, "size of `%s' is %u bytes", units);
- }
+ rest_of_decl_compilation (decl, NULL_PTR, DECL_CONTEXT (decl) == 0, 0);
}
-#if 0
- /* Resume permanent allocation, if not within a function. */
- /* The corresponding push_obstacks_nochange is in start_decl,
- and in push_parm_decl and in grokfield. */
- pop_obstacks ();
-#endif
-
- /* If we have gone back from temporary to permanent allocation,
- actually free the temporary space that we no longer need. */
- if (temporary && !allocation_temporary_p ())
- permanent_allocation (0);
-
/* At the end of a declaration, throw away any variable type sizes
of types defined inside that declaration. There is no use
computing them in the following function definition. */
/* Don't try computing parm sizes now -- wait till fn is called. */
immediate_size_expand = 0;
- /* The corresponding pop_obstacks is in finish_decl. */
- push_obstacks_nochange ();
-
decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
TREE_PURPOSE (TREE_PURPOSE (parm)), PARM, 0);
decl_attributes (decl, TREE_VALUE (TREE_VALUE (parm)),
else if (TREE_CODE (initial_value) == CONSTRUCTOR)
{
tree elts = CONSTRUCTOR_ELTS (initial_value);
- maxindex = size_binop (MINUS_EXPR, integer_zero_node, size_one_node);
+ maxindex = build_int_2 (-1, -1);
for (; elts; elts = TREE_CHAIN (elts))
{
if (TREE_PURPOSE (elts))
maxindex = TREE_PURPOSE (elts);
else
- maxindex = size_binop (PLUS_EXPR, maxindex, size_one_node);
+ maxindex = fold (build (PLUS_EXPR, integer_type_node,
+ maxindex, integer_one_node));
}
maxindex = copy_node (maxindex);
}
if (decl_context == FUNCDEF)
funcdef_flag = 1, decl_context = NORMAL;
- push_obstacks_nochange ();
-
- if (flag_traditional && allocation_temporary_p ())
- end_temporary_allocation ();
-
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
{
error ("`long long long' is too long for GCC");
else
{
- if (pedantic && ! in_system_header && warn_long_long)
+ if (pedantic && !flag_isoc99 && ! in_system_header
+ && warn_long_long)
pedwarn ("ANSI C does not support `long long'");
longlong = 1;
}
| (1 << (int) RID_UNSIGNED))))
/* Don't warn about typedef foo = bar. */
&& ! (specbits & (1 << (int) RID_TYPEDEF) && initialized)
- && ! (in_system_header && ! allocation_temporary_p ()))
+ && ! in_system_header)
{
- /* Issue a warning if this is an ISO C 9x program or if -Wreturn-type
+ /* Issue a warning if this is an ISO C 99 program or if -Wreturn-type
and this is a function, or if -Wimplicit; prefer the former
warning since it is more explicit. */
if ((warn_implicit_int || warn_return_type) && funcdef_flag)
warn_about_return_type = 1;
- else if (warn_implicit_int || flag_isoc9x)
- warning ("type defaults to `int' in declaration of `%s'", name);
+ else if (warn_implicit_int || flag_isoc99)
+ pedwarn_c99 ("type defaults to `int' in declaration of `%s'", name);
}
defaulted_int = 1;
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)
+ if (constp > 1 && ! flag_isoc99)
pedwarn ("duplicate `const'");
- if (restrictp > 1)
+ if (restrictp > 1 && ! flag_isoc99)
pedwarn ("duplicate `restrict'");
- if (volatilep > 1)
+ if (volatilep > 1 && ! flag_isoc99)
pedwarn ("duplicate `volatile'");
if (! flag_gen_aux_info && (TYPE_QUALS (type)))
type = TYPE_MAIN_VARIANT (type);
{
register tree itype = NULL_TREE;
register tree size = TREE_OPERAND (declarator, 1);
- /* An uninitialized decl with `extern' is a reference. */
- int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN));
/* The index is a signed object `sizetype' bits wide. */
tree index_type = signed_type (sizetype);
/* Check for some types that there cannot be arrays of. */
- if (TYPE_MAIN_VARIANT (type) == void_type_node)
+ if (VOID_TYPE_P (type))
{
error ("declaration of `%s' as array of voids", name);
type = error_mark_node;
if (type == error_mark_node)
continue;
- /* If this is a block level extern, it must live past the end
- of the function so that we can check it against other extern
- declarations (IDENTIFIER_LIMBO_VALUE). */
- if (extern_ref && allocation_temporary_p ())
- end_temporary_allocation ();
-
/* If size was specified, set ITYPE to a range-type for that size.
Otherwise, ITYPE remains null. finish_decl may figure it out
from an initial value. */
union incomplete (*foo)[4]; */
/* Complain about arrays of incomplete types, except in typedefs. */
- if (TYPE_SIZE (type) == 0
+ if (!COMPLETE_TYPE_P (type)
/* Avoid multiple warnings for nested array types. */
&& TREE_CODE (type) != ARRAY_TYPE
&& !(specbits & (1 << (int) RID_TYPEDEF))
}
else if (TREE_CODE (declarator) == CALL_EXPR)
{
- int extern_ref = (!(specbits & (1 << (int) RID_AUTO))
- || current_binding_level == global_binding_level);
tree arg_types;
/* Declaring a function type.
type = double_type_node;
#endif /* TRADITIONAL_RETURN_FLOAT */
- /* If this is a block level extern, it must live past the end
- of the function so that we can check it against other extern
- declarations (IDENTIFIER_LIMBO_VALUE). */
- if (extern_ref && allocation_temporary_p ())
- end_temporary_allocation ();
-
/* Construct the function type and go to the next
inner layer of declarator. */
only for the CALL_EXPR
closest to the identifier. */
&& TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE);
-#if 0 /* This seems to be false. We turn off temporary allocation
- above in this function if -traditional.
- And this code caused inconsistent results with prototypes:
- callers would ignore them, and pass arguments wrong. */
-
- /* Omit the arg types if -traditional, since the arg types
- and the list links might not be permanent. */
- type = build_function_type (type,
- flag_traditional
- ? NULL_TREE : arg_types);
-#endif
/* Type qualifiers before the return type of the function
qualify the return type, not the function type. */
if (type_quals)
error ("invalid type modifier within pointer declarator");
}
}
- if (constp > 1)
+ if (constp > 1 && ! flag_isoc99)
pedwarn ("duplicate `const'");
- if (volatilep > 1)
+ if (volatilep > 1 && ! flag_isoc99)
pedwarn ("duplicate `volatile'");
- if (restrictp > 1)
+ if (restrictp > 1 && ! flag_isoc99)
pedwarn ("duplicate `restrict'");
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
/* Did array size calculations overflow? */
if (TREE_CODE (type) == ARRAY_TYPE
- && TYPE_SIZE (type)
+ && COMPLETE_TYPE_P (type)
&& TREE_OVERFLOW (TYPE_SIZE (type)))
error ("size of array `%s' is too large", name);
if ((specbits & (1 << (int) RID_SIGNED))
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
- pop_obstacks ();
return decl;
}
pedwarn ("ANSI C forbids const or volatile function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
- pop_obstacks ();
return type;
}
We don't complain about parms either, but that is because
a better error message can be made later. */
- if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM
+ 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
error ("field `%s' declared as a function", name);
type = build_pointer_type (type);
}
- else if (TREE_CODE (type) != ERROR_MARK && TYPE_SIZE (type) == 0)
+ 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;
#endif
}
decl = build_decl (FIELD_DECL, declarator, type);
+ DECL_NONADDRESSABLE_P (decl) = bitfield;
+
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
}
&& pedantic)
pedwarn ("invalid storage class for function `%s'", name);
- /* If this is a block level extern, it must live past the end
- of the function so that we can check it against other
- extern declarations (IDENTIFIER_LIMBO_VALUE). */
- if (extern_ref && allocation_temporary_p ())
- end_temporary_allocation ();
-
decl = build_decl (FUNCTION_DECL, declarator, type);
decl = build_decl_attribute_variant (decl, decl_machine_attr);
pedwarn ("ANSI C forbids qualified function types");
if (pedantic
- && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node
+ && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
&& TYPE_QUALS (TREE_TYPE (TREE_TYPE (decl)))
&& ! DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ANSI C forbids qualified void function return type");
/* GNU C interprets a `volatile void' return type to indicate
that the function does not return. */
if ((type_quals & TYPE_QUAL_VOLATILE)
- && TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
+ && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
warning ("`noreturn' function returns non-void value");
if (extern_ref)
#endif
}
- /* If this is a block level extern, it must live past the end
- of the function so that we can check it against other
- extern declarations (IDENTIFIER_LIMBO_VALUE). */
- if (extern_ref && allocation_temporary_p ())
- end_temporary_allocation ();
-
decl = build_decl (VAR_DECL, declarator, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
mark_addressable (decl);
- pop_obstacks ();
-
return decl;
}
}
{
/* Barf if the parameter itself has an incomplete type. */
tree type = TREE_VALUE (typelt);
- if (TYPE_SIZE (type) == 0)
+ if (!COMPLETE_TYPE_P (type))
{
if (funcdef_flag && DECL_NAME (parm) != 0)
error ("parameter `%s' has incomplete type",
|| TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
type = TYPE_MAIN_VARIANT (type);
- if (TYPE_SIZE (type) == 0)
+ if (!COMPLETE_TYPE_P (type))
{
if (DECL_NAME (parm) != 0)
warning ("parameter `%s' points to incomplete type",
typelt = TREE_CHAIN (typelt);
}
- /* Allocate the list of types the way we allocate a type. */
- if (first_parm && ! TREE_PERMANENT (first_parm))
- {
- /* Construct a copy of the list of types
- on the saveable obstack. */
- tree result = NULL;
- for (typelt = first_parm; typelt; typelt = TREE_CHAIN (typelt))
- result = saveable_tree_cons (NULL_TREE, TREE_VALUE (typelt),
- result);
- return nreverse (result);
- }
- else
- /* The list we have is permanent already. */
return first_parm;
}
}
tree new_parms = 0;
tree order = current_binding_level->parm_order;
- /* Just `void' (and no ellipsis) is special. There are really no parms. */
+ /* Just `void' (and no ellipsis) is special. There are really no parms.
+ But if the `void' is qualified (by `const' or `volatile') or has a
+ storage class specifier (`register'), then the behavior is undefined;
+ by not counting it as the special case of `void' we will cause an
+ error later. Typedefs for `void' are OK (see DR#157).
+ */
if (void_at_end && parms != 0
&& TREE_CHAIN (parms) == 0
- && TYPE_MAIN_VARIANT (TREE_TYPE (parms)) == void_type_node
+ && 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 saveable_tree_cons (NULL_TREE, NULL_TREE,
- saveable_tree_cons (NULL_TREE, void_type_node, NULL_TREE));
+ return tree_cons (NULL_TREE, NULL_TREE,
+ tree_cons (NULL_TREE, void_type_node, NULL_TREE));
}
/* Extract enumerator values and other non-parms declared with the parms.
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (decl) = integer_type_node;
- types = saveable_tree_cons (NULL_TREE, TREE_TYPE (decl), types);
- if (TYPE_MAIN_VARIANT (TREE_VALUE (types)) == void_type_node && ! erred
+ 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");
}
if (void_at_end)
- return saveable_tree_cons (new_parms, tags,
- nreverse (saveable_tree_cons (NULL_TREE, void_type_node, types)));
+ return tree_cons (new_parms, tags,
+ nreverse (tree_cons (NULL_TREE, void_type_node, types)));
- return saveable_tree_cons (new_parms, tags, nreverse (types));
+ return tree_cons (new_parms, tags, nreverse (types));
}
/* At end of parameter list, warn about any struct, union or enum tags
: "enum"),
IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
else
- warning ("anonymous %s declared inside parameter list",
- (code == RECORD_TYPE ? "struct"
- : code == UNION_TYPE ? "union"
- : "enum"));
-
+ {
+ /* For translation these need to be seperate warnings */
+ 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.");
enum tree_code code;
tree name;
{
- int temporary = allocation_temporary_p ();
-
/* If a cross reference is requested, look up the type
already defined for this tag and return it. */
if (ref)
return ref;
- push_obstacks_nochange ();
-
- if (current_binding_level == global_binding_level && temporary)
- end_temporary_allocation ();
-
/* If no such tag is yet defined, create a forward-reference node
and record it as the "definition".
When a real declaration of this type is found,
to avoid crashing if it does not get defined. */
TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
+ 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);
pushtag (name, ref);
- pop_obstacks ();
-
return ref;
}
\f
/* Make sure that the tag NAME is defined *in the current binding level*
at least as a forward reference.
- CODE says which kind of tag NAME ought to be.
-
- We also do a push_obstacks_nochange
- whose matching pop is in finish_struct. */
+ CODE says which kind of tag NAME ought to be. */
tree
start_struct (code, name)
register tree ref = 0;
- push_obstacks_nochange ();
- if (current_binding_level == global_binding_level)
- end_temporary_allocation ();
-
if (name != 0)
ref = lookup_tag (code, name, current_binding_level, 1);
if (ref && TREE_CODE (ref) == code)
{
tree value;
- /* The corresponding pop_obstacks is in finish_decl. */
- push_obstacks_nochange ();
-
value = grokdeclarator (declarator, declspecs, width ? BITFIELD : FIELD, 0);
finish_decl (value, NULL_TREE, NULL_TREE);
\f
/* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
FIELDLIST is a chain of FIELD_DECL nodes for the fields.
- ATTRIBUTES are attributes to be applied to the structure.
-
- We also do a pop_obstacks to match the push in start_struct. */
+ ATTRIBUTES are attributes to be applied to the structure. */
tree
finish_struct (t, fieldlist, attributes)
tree attributes;
{
register tree x;
- int old_momentary;
int toplevel = global_binding_level == current_binding_level;
/* If this type was previously laid out as a forward reference,
{
if (pedantic)
pedwarn ("%s defined inside parms",
- TREE_CODE (t) == UNION_TYPE ? "union" : "structure");
+ TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
else if (! flag_traditional)
warning ("%s defined inside parms",
- TREE_CODE (t) == UNION_TYPE ? "union" : "structure");
+ TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
}
- old_momentary = suspend_momentary ();
-
if (pedantic)
{
for (x = fieldlist; x; x = TREE_CHAIN (x))
break;
if (x == 0)
- pedwarn ("%s has no %smembers",
- TREE_CODE (t) == UNION_TYPE ? "union" : "struct",
- fieldlist ? "named " : "");
+ pedwarn ("%s has no %s",
+ TREE_CODE (t) == UNION_TYPE ? _("union") : _("struct"),
+ fieldlist ? _("named members") : _("members"));
}
/* Install struct as DECL_CONTEXT of each field decl.
- Also process specified field sizes.
- Set DECL_FIELD_SIZE to the specified size, or 0 if none specified.
- The specified size is found in the DECL_INITIAL.
+ Also process specified field sizes,m which is found in the DECL_INITIAL.
Store 0 there, except for ": 0" fields (so we can find them
and delete them, below). */
{
DECL_CONTEXT (x) = t;
DECL_PACKED (x) |= TYPE_PACKED (t);
- DECL_FIELD_SIZE (x) = 0;
/* If any field is const, the structure type is pseudo-const. */
if (TREE_READONLY (x))
constant_expression_warning (DECL_INITIAL (x));
else
{
- error_with_decl (x, "bit-field `%s' width not an integer constant");
+ error_with_decl (x,
+ "bit-field `%s' width not an integer constant");
DECL_INITIAL (x) = NULL;
}
}
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_PRECISION (integer_type_node))))
pedwarn_with_decl (x, "bit-field `%s' type invalid in ANSI C");
- /* Detect and ignore out of range field width. */
+ /* Detect and ignore out of range field width and process valid
+ field widths. */
if (DECL_INITIAL (x))
{
- unsigned HOST_WIDE_INT width = TREE_INT_CST_LOW (DECL_INITIAL (x));
-
if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
+ error_with_decl (x, "negative width in bit-field `%s'");
+ else if (0 < compare_tree_int (DECL_INITIAL (x),
+ TYPE_PRECISION (TREE_TYPE (x))))
+ 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
{
- DECL_INITIAL (x) = NULL;
- error_with_decl (x, "negative width in bit-field `%s'");
- }
- else if (TREE_INT_CST_HIGH (DECL_INITIAL (x)) != 0
- || width > TYPE_PRECISION (TREE_TYPE (x)))
- {
- DECL_INITIAL (x) = NULL;
- pedwarn_with_decl (x, "width of `%s' exceeds its type");
- }
- else if (width == 0 && DECL_NAME (x) != 0)
- {
- error_with_decl (x, "zero width for bit-field `%s'");
- DECL_INITIAL (x) = NULL;
- }
- }
-
- /* Process valid field width. */
- if (DECL_INITIAL (x))
- {
- register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
-
- if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
- && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
- TREE_UNSIGNED (TREE_TYPE (x)))
- || width < min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
- TREE_UNSIGNED (TREE_TYPE (x)))))
- warning_with_decl (x, "`%s' is narrower than values of its type");
-
- DECL_FIELD_SIZE (x) = width;
- DECL_BIT_FIELD (x) = DECL_C_BIT_FIELD (x) = 1;
- DECL_INITIAL (x) = NULL;
-
- if (width == 0)
- {
- /* field size 0 => force desired amount of alignment. */
+ /* The test above has assured us that TREE_INT_CST_HIGH is 0. */
+ unsigned HOST_WIDE_INT width
+ = TREE_INT_CST_LOW (DECL_INITIAL (x));
+
+ if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
+ && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
+ TREE_UNSIGNED (TREE_TYPE (x)))
+ || (width
+ < min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
+ TREE_UNSIGNED (TREE_TYPE (x))))))
+ warning_with_decl (x,
+ "`%s' is narrower than values of its type");
+
+ DECL_SIZE (x) = bitsize_int (width);
+ DECL_BIT_FIELD (x) = DECL_C_BIT_FIELD (x) = 1;
+
+ if (width == 0)
+ {
+ /* field size 0 => force desired amount of alignment. */
#ifdef EMPTY_FIELD_BOUNDARY
- DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
+ 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)));
+ 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)));
+ : TYPE_ALIGN (TREE_TYPE (x)));
+
/* Non-bit-fields are aligned for their type, except packed
fields which require only BITS_PER_UNIT alignment. */
DECL_ALIGN (x) = MAX (DECL_ALIGN (x), min_align);
+ if (! DECL_PACKED (x))
+ DECL_USER_ALIGN (x) |= TYPE_USER_ALIGN (TREE_TYPE (x));
}
- }
- /* Now DECL_INITIAL is null on all members. */
+ DECL_INITIAL (x) = 0;
+ }
/* Delete all duplicate fields from the fieldlist */
for (x = fieldlist; x && TREE_CHAIN (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 this was supposed to be a transparent union, but we can't
expand_decl (decl);
--current_binding_level->n_incomplete;
}
- else if (TYPE_SIZE (TREE_TYPE (decl)) == 0
+ else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
{
tree element = TREE_TYPE (decl);
}
}
- resume_momentary (old_momentary);
-
/* Finish debugging output for this type. */
rest_of_type_compilation (t, toplevel);
- /* The matching push is in start_struct. */
- pop_obstacks ();
-
return t;
}
if (name != 0)
enumtype = lookup_tag (ENUMERAL_TYPE, name, current_binding_level, 1);
- /* The corresponding pop_obstacks is in finish_enum. */
- push_obstacks_nochange ();
- /* If these symbols and types are global, make them permanent. */
- if (current_binding_level == global_binding_level)
- end_temporary_allocation ();
-
if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE)
{
enumtype = make_node (ENUMERAL_TYPE);
tree attributes;
{
register tree pair, tem;
- tree minnode = 0, maxnode = 0;
+ tree minnode = 0, maxnode = 0, enum_value_type;
int precision, unsign;
int toplevel = (global_binding_level == current_binding_level);
precision = TYPE_PRECISION (long_long_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_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);
- DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu));
+
+ /* The ISO C Standard mandates enumerators to have type int,
+ even though the underlying type of an enum type is
+ unspecified. Here we convert any enumerators that fit in
+ an int to type int, to avoid promotions to unsigned types
+ when comparing integers with enumerators that fit in the
+ int range. When -pedantic is given, build_enumerator()
+ would have already taken care of those that don't fit. */
+ 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_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);
}
/* Finish debugging output for this type. */
rest_of_type_compilation (enumtype, toplevel);
- /* This matches a push in start_enum. */
- pop_obstacks ();
-
return enumtype;
}
if (pedantic && ! int_fits_type_p (value, integer_type_node))
{
pedwarn ("ANSI C restricts enumerator values to range of `int'");
- value = integer_zero_node;
+ value = convert (integer_type_node, value);
}
/* Set basis for default for next value. */
&& TREE_UNSIGNED (type)));
decl = build_decl (CONST_DECL, name, type);
- DECL_INITIAL (decl) = value;
- TREE_TYPE (value) = type;
+ DECL_INITIAL (decl) = convert (type, value);
pushdecl (decl);
- return saveable_tree_cons (decl, value, NULL_TREE);
+ return tree_cons (decl, value, NULL_TREE);
}
\f
/* Create the FUNCTION_DECL for a function definition.
Returns 1 on success. If the DECLARATOR is not suitable for a function
(it defines a datum instead), we return 0, which tells
- yyparse to report a parse error.
-
- NESTED is nonzero for a function nested within another function. */
+ yyparse to report a parse error. */
int
-start_function (declspecs, declarator, prefix_attributes, attributes, nested)
+start_function (declspecs, declarator, prefix_attributes, attributes)
tree declarator, declspecs, prefix_attributes, attributes;
- int nested;
{
tree decl1, old_decl;
tree restype;
announce_function (decl1);
- if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl1))) == 0)
+ if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1))))
{
- error ("return-type is an incomplete type");
+ error ("return type is an incomplete type");
/* Make it return void instead. */
TREE_TYPE (decl1)
= build_function_type (void_type_node,
}
if (warn_about_return_type)
- warning ("return-type defaults to `int'");
+ pedwarn_c99 ("return type defaults to `int'");
/* Save the parm names or decls from this function's declarator
where store_parm_decls will find them. */
DECL_RESULT (current_function_decl)
= build_decl (RESULT_DECL, NULL_TREE, restype);
- if (!nested)
- /* Allocate further tree nodes temporarily during compilation
- of this function only. */
- temporary_allocation ();
-
/* If this fcn was already referenced via a block-scope `extern' decl
(or an implicit decl), propagate certain information about the usage. */
if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl)))
{
if (DECL_NAME (parm) == 0)
error_with_decl (parm, "parameter name omitted");
- else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node)
+ else if (TREE_CODE (TREE_TYPE (parm)) != ERROR_MARK
+ && VOID_TYPE_P (TREE_TYPE (parm)))
{
error_with_decl (parm, "parameter `%s' declared void");
/* Change the type to error_mark_node so this parameter
Associate decls with the names and store the decls
into the TREE_PURPOSE slots. */
+ /* We use DECL_WEAK as a flag to show which parameters have been
+ seen already since it is not used on PARM_DECL or CONST_DECL. */
for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
- DECL_RESULT (parm) = 0;
+ DECL_WEAK (parm) = 0;
for (parm = specparms; parm; parm = TREE_CHAIN (parm))
{
if (TREE_VALUE (parm) == 0)
{
- error_with_decl (fndecl, "parameter name missing from parameter list");
+ error_with_decl (fndecl,
+ "parameter name missing from parameter list");
TREE_PURPOSE (parm) = 0;
continue;
}
/* If declaration already marked, we have a duplicate name.
Complain, and don't use this decl twice. */
- if (found && DECL_RESULT (found) != 0)
+ if (found && DECL_WEAK (found))
{
error_with_decl (found, "multiple parameters named `%s'");
found = 0;
}
/* If the declaration says "void", complain and ignore it. */
- if (found && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == void_type_node)
+ 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) = TREE_TYPE (found);
DECL_SOURCE_LINE (found) = DECL_SOURCE_LINE (fndecl);
DECL_SOURCE_FILE (found) = DECL_SOURCE_FILE (fndecl);
- if (extra_warnings)
+ 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;
- /* Mark this decl as "already found" -- see test, above.
- It is safe to use DECL_RESULT for this
- since it is not used in PARM_DECLs or CONST_DECLs. */
- DECL_RESULT (found) = error_mark_node;
+ /* Mark this decl as "already found" */
+ DECL_WEAK (found) = 1;
}
/* Put anything which is on the parmdecls chain and which is
else
{
/* Complain about args with incomplete types. */
- if (TYPE_SIZE (TREE_TYPE (parm)) == 0)
+ if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
{
error_with_decl (parm, "parameter `%s' has incomplete type");
TREE_TYPE (parm) = error_mark_node;
}
- if (DECL_RESULT (parm) == 0)
+ if (! DECL_WEAK (parm))
{
error_with_decl (parm,
"declaration for parameter `%s' but no such parameter");
for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
{
- type = perm_tree_cons (NULL_TREE, DECL_ARG_TYPE (parm),
- NULL_TREE);
+ type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
if (last)
TREE_CHAIN (last) = type;
else
actual = type;
last = type;
}
- type = perm_tree_cons (NULL_TREE, void_type_node, NULL_TREE);
+ type = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
if (last)
TREE_CHAIN (last) = type;
else
tree types = 0;
for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
- DECL_RESULT (parm) = 0;
+ DECL_WEAK (parm) = 0;
for (parm = specparms; parm; parm = TREE_CHAIN (parm))
{
/* If declaration already marked, we have a duplicate name.
Complain, and don't use this decl twice. */
- if (found && DECL_RESULT (found) != 0)
+ if (found && DECL_WEAK (found))
{
error_with_decl (found, "multiple parameters named `%s'");
found = 0;
}
/* If the declaration says "void", complain and ignore it. */
- if (found && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == void_type_node)
+ if (found && VOID_TYPE_P (TREE_TYPE (found)))
{
error_with_decl (found, "parameter `%s' declared void");
TREE_TYPE (found) = integer_type_node;
TREE_PURPOSE (parm) = found;
- /* Mark this decl as "already found" -- see test, above.
- It is safe to use DECL_RESULT for this
- since it is not used in PARM_DECLs or CONST_DECLs. */
- DECL_RESULT (found) = error_mark_node;
+ /* Mark this decl as "already found". */
+ DECL_WEAK (found) = 1;
}
/* Complain about any actual PARM_DECLs not matched with any names. */
TREE_CHAIN (parm) = 0;
/* Complain about args with incomplete types. */
- if (TYPE_SIZE (TREE_TYPE (parm)) == 0)
+ if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
{
error_with_decl (parm, "parameter `%s' has incomplete type");
TREE_TYPE (parm) = error_mark_node;
}
- if (DECL_RESULT (parm) == 0)
+ if (! DECL_WEAK (parm))
{
error_with_decl (parm,
"declaration for parameter `%s' but no such parameter");
last = TREE_PURPOSE (parm);
TREE_CHAIN (last) = 0;
- types = saveable_tree_cons (NULL_TREE, TREE_TYPE (parm), types);
+ types = tree_cons (NULL_TREE, TREE_TYPE (parm), types);
}
}
if (void_at_end)
- return saveable_tree_cons (parmdecls, nonparms,
- nreverse (saveable_tree_cons (NULL_TREE,
- void_type_node,
- types)));
+ return tree_cons (parmdecls, nonparms,
+ nreverse (tree_cons (NULL_TREE, void_type_node, types)));
- return saveable_tree_cons (parmdecls, nonparms, nreverse (types));
+ return tree_cons (parmdecls, nonparms, nreverse (types));
}
\f
/* Finish up a function declaration and compile that function
setjmp_protect_args ();
}
- if (! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main"))
+ if (! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")
+ && flag_hosted)
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
!= integer_type_node)
#ifdef DEFAULT_MAIN_RETURN
/* Make it so that `main' always returns success by default. */
DEFAULT_MAIN_RETURN;
+#else
+ if (flag_isoc99)
+ c_expand_return (integer_zero_node);
#endif
}
}
/* If this is a nested function, protect the local variables in the stack
above us from being collected while we're compiling this function. */
- if (ggc_p && nested)
+ if (nested)
ggc_push_context ();
/* Run the optimizers and output the assembler code for this function. */
rest_of_compilation (fndecl);
/* Undo the GC context switch. */
- if (ggc_p && nested)
+ if (nested)
ggc_pop_context ();
current_function_returns_null |= can_reach_end;
if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
warning ("`noreturn' function does return");
else if (warn_return_type && can_reach_end
- && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) != void_type_node)
+ && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
/* If this function returns non-void and control can drop through,
complain. */
warning ("control reaches end of non-void function");
if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
{
- register tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
+ tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
- if (ret_type)
+ if (ret_type && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
+ && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
+ larger_than_size))
{
- register tree ret_type_size = TYPE_SIZE (ret_type);
-
- if (TREE_CODE (ret_type_size) == INTEGER_CST)
- {
- unsigned units
- = TREE_INT_CST_LOW (ret_type_size) / BITS_PER_UNIT;
+ unsigned int size_as_int
+ = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
- if (units > larger_than_size)
- warning_with_decl (fndecl,
- "size of return value of `%s' is %u bytes",
- units);
- }
+ 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);
}
}
- /* Free all the tree nodes making up this function. */
- /* Switch back to allocating nodes permanently
- until we start another function. */
- if (! nested)
- permanent_allocation (1);
-
if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested)
{
- /* Stop pointing to the local nodes about to be freed. */
- /* But DECL_INITIAL must remain nonzero so we know this
- was an actual function definition. */
- /* For a nested function, this is done in pop_c_function_context. */
- /* If rest_of_compilation set this to 0, leave it 0. */
+ /* Stop pointing to the local nodes about to be freed.
+ But DECL_INITIAL must remain nonzero so we know this
+ was an actual function definition.
+ For a nested function, this is done in pop_c_function_context.
+ If rest_of_compilation set this to 0, leave it 0. */
if (DECL_INITIAL (fndecl) != 0)
DECL_INITIAL (fndecl) = error_mark_node;
+
DECL_ARGUMENTS (fndecl) = 0;
}
{
#ifndef ASM_OUTPUT_CONSTRUCTOR
if (! flag_gnu_linker)
- static_ctors = perm_tree_cons (NULL_TREE, fndecl, static_ctors);
+ static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
else
#endif
assemble_constructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
{
#ifndef ASM_OUTPUT_DESTRUCTOR
if (! flag_gnu_linker)
- static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors);
+ static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
else
#endif
assemble_destructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
ggc_mark (TYPE_LANG_SPECIFIC (t));
}
+
+/* The functions below are required for functionality of doing
+ function at once processing in the C front end. Currently these
+ functions are not called from anywhere in the C front end, but as
+ these changes continue, that will change. */
+
+/* Returns non-zero if the current statement is a full expression,
+ i.e. temporaries created during that statement should be destroyed
+ at the end of the statement. */
+
+int
+stmts_are_full_exprs_p ()
+{
+ return 0;
+}
+
+/* Nonzero if TYPE is an anonymous union or struct type. Always 0 in
+ C. */
+
+int
+anon_aggr_type_p (node)
+ tree node ATTRIBUTE_UNUSED;
+{
+ return 0;
+}
+
+/* One if we have already declared __FUNCTION__ (and related
+ variables) in the current function. Two if we are in the process
+ of doing so. */
+
+int
+current_function_name_declared ()
+{
+ abort ();
+ return 0;
+}
+
+/* Code to generate the RTL for a case label in C. */
+
+void
+do_case (low_value, high_value)
+ tree low_value;
+ tree high_value;
+{
+ tree value1 = NULL_TREE, value2 = NULL_TREE, label;
+
+ if (low_value != NULL_TREE)
+ value1 = check_case_value (low_value);
+ if (high_value != NULL_TREE)
+ value2 = check_case_value (high_value);
+
+ label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+
+ if (pedantic && (high_value != NULL_TREE))
+ pedwarn ("ANSI C forbids case ranges");
+
+ if (value1 != error_mark_node && value2 != error_mark_node)
+ {
+ tree duplicate;
+ int success;
+
+ if (high_value == NULL_TREE && value1 != NULL_TREE &&
+ pedantic && ! INTEGRAL_TYPE_P (TREE_TYPE (value1)))
+ pedwarn ("label must have integral type in ANSI C");
+
+ if (low_value == NULL_TREE)
+ success = pushcase (NULL_TREE, 0, label, &duplicate);
+ else if (high_value == NULL_TREE)
+ success = pushcase (value1, convert_and_check, label,
+ &duplicate);
+ else
+ success = pushcase_range (value1, value2, convert_and_check,
+ label, &duplicate);
+
+ if (success == 1)
+ {
+ if (low_value == NULL_TREE)
+ error ("default label not within a switch statement");
+ else
+ error ("case label not within a switch statement");
+ }
+ else if (success == 2) {
+ if (low_value == NULL_TREE)
+ {
+ error ("multiple default labels in one switch");
+ error_with_decl (duplicate, "this is the first default label");
+ }
+ else
+ error ("dupicate case value");
+ if (high_value != NULL_TREE)
+ error_with_decl (duplicate, "this is the first entry for that value");
+ }
+ else if (low_value != NULL_TREE)
+ {
+ if (success == 3)
+ warning ("case value out of range");
+ else if (success == 5)
+ error ("case label within scope of cleanup or variable array");
+ }
+ }
+}
+
+/* Language specific handler of tree nodes used when generating RTL
+ from a tree. */
+
+tree
+lang_expand_stmt (t)
+ tree t ATTRIBUTE_UNUSED;
+{
+ abort ();
+ return NULL_TREE;
+}
+
+/* Accessor to set the 'current_function_name_declared' flag. */
+
+void
+set_current_function_name_declared (i)
+ int i ATTRIBUTE_UNUSED;
+{
+ abort ();
+}
+