summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/c-decl.c
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2002-02-01 18:16:02 +0000
committerobrien <obrien@FreeBSD.org>2002-02-01 18:16:02 +0000
commitc9ab9ae440a8066b2c2b85b157b1fdadcf09916a (patch)
tree086d9d6c8fbd4fc8fe4495059332f66bc0f8d12b /contrib/gcc/c-decl.c
parent2ecfd8bd04b63f335c1ec6295740a4bfd97a4fa6 (diff)
downloadFreeBSD-src-c9ab9ae440a8066b2c2b85b157b1fdadcf09916a.zip
FreeBSD-src-c9ab9ae440a8066b2c2b85b157b1fdadcf09916a.tar.gz
Enlist the FreeBSD-CURRENT users as testers of what is to become Gcc 3.1.0.
These bits are taken from the FSF anoncvs repo on 1-Feb-2002 08:20 PST.
Diffstat (limited to 'contrib/gcc/c-decl.c')
-rw-r--r--contrib/gcc/c-decl.c4463
1 files changed, 2235 insertions, 2228 deletions
diff --git a/contrib/gcc/c-decl.c b/contrib/gcc/c-decl.c
index 6f8a900..4153f50 100644
--- a/contrib/gcc/c-decl.c
+++ b/contrib/gcc/c-decl.c
@@ -1,24 +1,23 @@
/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
- Free Software Foundation, Inc.
+ Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001, 2002 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
/* Process declarations and symbol lookup for C front end.
Also constructs types; the standard scalar types at initialization,
@@ -29,17 +28,24 @@ Boston, MA 02111-1307, USA. */
#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"
-
-#if USE_CPPLIB
+#include "ggc.h"
+#include "tm_p.h"
#include "cpplib.h"
-extern cpp_reader parse_in;
-#endif
+#include "target.h"
+#include "debug.h"
+#include "timevar.h"
+#include "c-common.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@@ -47,185 +53,15 @@ enum decl_context
FUNCDEF, /* Function definition */
PARM, /* Declaration of parm before function body */
FIELD, /* Declaration inside struct or union */
- BITFIELD, /* Likewise but with specified width */
TYPENAME}; /* Typename (inside cast or sizeof) */
-#ifndef CHAR_TYPE_SIZE
-#define CHAR_TYPE_SIZE BITS_PER_UNIT
-#endif
-
-#ifndef SHORT_TYPE_SIZE
-#define SHORT_TYPE_SIZE (BITS_PER_UNIT * MIN ((UNITS_PER_WORD + 1) / 2, 2))
-#endif
-
-#ifndef INT_TYPE_SIZE
-#define INT_TYPE_SIZE BITS_PER_WORD
-#endif
-
-#ifndef LONG_TYPE_SIZE
-#define LONG_TYPE_SIZE BITS_PER_WORD
-#endif
-
-#ifndef LONG_LONG_TYPE_SIZE
-#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
-#endif
-
-#ifndef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
-#endif
-
-#ifndef FLOAT_TYPE_SIZE
-#define FLOAT_TYPE_SIZE BITS_PER_WORD
-#endif
-
-#ifndef DOUBLE_TYPE_SIZE
-#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
-#endif
-
-#ifndef LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
-#endif
-
-/* We let tm.h override the types used here, to handle trivial differences
- such as the choice of unsigned int or long unsigned int for size_t.
- When machines start needing nontrivial differences in the size type,
- it would be best to do something here to figure out automatically
- from other information what type to use. */
-
-#ifndef SIZE_TYPE
-#define SIZE_TYPE "long unsigned int"
-#endif
-
-#ifndef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-#endif
-
-#ifndef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-#endif
-/* a node which has tree code ERROR_MARK, and whose type is itself.
- All erroneous expressions are replaced with this node. All functions
- that accept nodes as arguments should avoid generating error messages
- if this node is one of the arguments, since it is undesirable to get
- multiple error messages from one error in the input. */
-
-tree error_mark_node;
-
-/* INTEGER_TYPE and REAL_TYPE nodes for the standard data types */
-
-tree short_integer_type_node;
-tree integer_type_node;
-tree long_integer_type_node;
-tree long_long_integer_type_node;
-
-tree short_unsigned_type_node;
-tree unsigned_type_node;
-tree long_unsigned_type_node;
-tree long_long_unsigned_type_node;
-
-tree boolean_type_node;
-tree boolean_false_node;
-tree boolean_true_node;
-
-tree ptrdiff_type_node;
-
-tree unsigned_char_type_node;
-tree signed_char_type_node;
-tree char_type_node;
-tree wchar_type_node;
-tree signed_wchar_type_node;
-tree unsigned_wchar_type_node;
-
-tree float_type_node;
-tree double_type_node;
-tree long_double_type_node;
-
-tree complex_integer_type_node;
-tree complex_float_type_node;
-tree complex_double_type_node;
-tree complex_long_double_type_node;
-
-tree intQI_type_node;
-tree intHI_type_node;
-tree intSI_type_node;
-tree intDI_type_node;
-#if HOST_BITS_PER_WIDE_INT >= 64
-tree intTI_type_node;
-#endif
-
-tree unsigned_intQI_type_node;
-tree unsigned_intHI_type_node;
-tree unsigned_intSI_type_node;
-tree unsigned_intDI_type_node;
-#if HOST_BITS_PER_WIDE_INT >= 64
-tree unsigned_intTI_type_node;
-#endif
-
-/* a VOID_TYPE node. */
-
-tree void_type_node;
-
-/* Nodes for types `void *' and `const void *'. */
-
-tree ptr_type_node, const_ptr_type_node;
-
-/* Nodes for types `char *' and `const char *'. */
-
-tree string_type_node, const_string_type_node;
-
-/* Type `char[SOMENUMBER]'.
- Used when an array of char is needed and the size is irrelevant. */
-
-tree char_array_type_node;
-
-/* Type `int[SOMENUMBER]' or something like it.
- Used when an array of int needed and the size is irrelevant. */
-
-tree int_array_type_node;
-
-/* Type `wchar_t[SOMENUMBER]' or something like it.
- Used when a wide string literal is created. */
-
-tree wchar_array_type_node;
-
-/* type `int ()' -- used for implicit declaration of functions. */
-
-tree default_function_type;
-
-/* function types `double (double)' and `double (double, double)', etc. */
-
-tree double_ftype_double, double_ftype_double_double;
-tree int_ftype_int, long_ftype_long;
-tree float_ftype_float;
-tree ldouble_ftype_ldouble;
-
-/* Function type `void (void *, void *, int)' and similar ones */
-
-tree void_ftype_ptr_ptr_int, int_ftype_ptr_ptr_int, void_ftype_ptr_int_int;
-
-/* Function type `char *(char *, char *)' and similar ones */
-tree string_ftype_ptr_ptr, int_ftype_string_string;
-
-/* Function type `int (const void *, const void *, size_t)' */
-tree int_ftype_cptr_cptr_sizet;
-
-/* Two expressions that are constants with value zero.
- The first is of type `int', the second of type `void *'. */
-
-tree integer_zero_node;
-tree null_pointer_node;
-
-/* A node for the integer constant 1. */
-
-tree integer_one_node;
-
/* Nonzero if we have seen an invalid cross reference
to a struct, union, or enum, but not yet printed the message. */
tree pending_invalid_xref;
/* File and line to appear in the eventual error message. */
-char *pending_invalid_xref_file;
+const char *pending_invalid_xref_file;
int pending_invalid_xref_line;
/* While defining an enum type, this is 1 plus the last enumerator
@@ -261,9 +97,17 @@ static tree current_function_parm_tags;
/* Similar, for the file and line that the prototype came from if this is
an old-style definition. */
-static char *current_function_prototype_file;
+static const char *current_function_prototype_file;
static int current_function_prototype_line;
+/* The current statement tree. */
+
+static struct stmt_tree_s c_stmt_tree;
+
+/* The current scope statement stack. */
+
+static tree c_scope_stmt_stack;
+
/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
that have names. Here so we can clear out their names' definitions
at the end of the function. */
@@ -279,10 +123,6 @@ static tree shadowed_labels;
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. */
@@ -369,7 +209,7 @@ struct binding_level
/* Nonzero means make a BLOCK if this level has any subblocks. */
char keep_if_subblocks;
- /* Number of decls in `names' that have incomplete
+ /* Number of decls in `names' that have incomplete
structure or union types. */
int n_incomplete;
@@ -380,7 +220,7 @@ struct binding_level
};
#define NULL_BINDING_LEVEL (struct binding_level *) NULL
-
+
/* The binding level currently in effect. */
static struct binding_level *current_binding_level;
@@ -409,7 +249,7 @@ static int keep_next_level_flag;
if it has subblocks. */
static int keep_next_if_subblocks;
-
+
/* The chain of outer levels of label scopes.
This uses the same data structure used for binding levels,
but it works differently: each link in the chain records
@@ -424,67 +264,67 @@ tree static_ctors, static_dtors;
/* Forward declarations. */
-static struct binding_level * make_binding_level PROTO((void));
-static void clear_limbo_values PROTO((tree));
-static int duplicate_decls PROTO((tree, tree, int));
-static int redeclaration_error_message PROTO((tree, tree));
-static void storedecls PROTO((tree));
-static void storetags PROTO((tree));
-static tree lookup_tag PROTO((enum tree_code, tree,
- struct binding_level *, int));
-static tree lookup_tag_reverse PROTO((tree));
-static tree grokdeclarator PROTO((tree, tree, enum decl_context,
- int));
-static tree grokparms PROTO((tree, int));
-static int field_decl_cmp PROTO((const GENERIC_PTR, const GENERIC_PTR));
-static void layout_array_type PROTO((tree));
+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, tree));
+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));
+static tree build_bitfield_integer_type PARAMS ((tree, tree, const char *));
/* C-specific option variables. */
/* Nonzero means allow type mismatches in conditional expressions;
- just make their values `void'. */
+ just make their values `void'. */
int flag_cond_mismatch;
-/* Nonzero means give `double' the same size as `float'. */
-
-int flag_short_double;
-
/* Nonzero means don't recognize the keyword `asm'. */
int flag_no_asm;
-/* Nonzero means don't recognize any builtin functions. */
-
-int flag_no_builtin;
-
-/* Nonzero means don't recognize the non-ANSI builtin functions.
- -ansi sets this. */
-
-int flag_no_nonansi_builtin;
-
/* Nonzero means do some things the same way PCC does. */
int flag_traditional;
-/* Nonzero means use the ISO C9x dialect of C. */
+/* Nonzero means enable C89 Amendment 1 features. */
-int flag_isoc9x = 0;
+int flag_isoc94 = 0;
+
+/* Nonzero means use the ISO C99 dialect of C. */
+
+int flag_isoc99 = 0;
/* Nonzero means that we have builtin functions, and main is an int */
int flag_hosted = 1;
+/* Nonzero means add default format_arg attributes for functions not
+ in ISO C. */
+
+int flag_noniso_default_format_attributes = 1;
+
/* Nonzero means to allow single precision math even if we're generally
being traditional. */
int flag_allow_single_precision = 0;
-/* Nonzero means to treat bitfields as signed unless they say `unsigned'. */
+/* Nonzero means to treat bit-fields as signed unless they say `unsigned'. */
int flag_signed_bitfields = 1;
int explicit_flag_signed_bitfields = 0;
-/* Nonzero means warn about use of implicit int. */
+/* Nonzero means warn about use of implicit int. */
int warn_implicit_int;
@@ -493,9 +333,9 @@ int warn_implicit_int;
int warn_long_long = 1;
/* Nonzero means message about use of implicit function declarations;
- 1 means warning; 2 means error. */
+ 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
@@ -514,9 +354,9 @@ int warn_cast_qual;
int warn_bad_function_cast;
-/* Warn about functions which might be candidates for attribute noreturn. */
+/* Warn about functions which might be candidates for format attributes. */
-int warn_missing_noreturn;
+int warn_missing_format_attribute;
/* Warn about traditional constructs whose meanings changed in ANSI C. */
@@ -555,10 +395,6 @@ int warn_redundant_decls = 0;
int warn_nested_externs = 0;
-/* Warn about *printf or *scanf format/argument anomalies. */
-
-int warn_format;
-
/* Warn about a subscript that has type char. */
int warn_char_subscripts = 0;
@@ -581,13 +417,17 @@ int warn_main;
/* Warn about #pragma directives that are not recognised. */
-int warn_unknown_pragmas = 0; /* Tri state variable. */
+int warn_unknown_pragmas = 0; /* Tri state variable. */
/* Warn about comparison of signed and unsigned values.
If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified. */
int warn_sign_compare = -1;
+/* Warn about testing equality of floating point numbers. */
+
+int warn_float_equal = 0;
+
/* Nonzero means warn about use of multicharacter literals. */
int warn_multichar = 1;
@@ -599,9 +439,22 @@ int warn_multichar = 1;
#endif
int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
-/* Decode the string P as a language-specific option for C.
- Return the number of strings consumed. */
+/* States indicating how grokdeclarator() should handle declspecs marked
+ with __attribute__((deprecated)). An object declared as
+ __attribute__((deprecated)) suppresses warnings of uses of other
+ deprecated items. */
+enum deprecated_states {
+ DEPRECATED_NORMAL,
+ DEPRECATED_SUPPRESS
+};
+
+static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
+
+/* Decode the string P as a language-specific option for C.
+ Return the number of strings consumed. Should not complain
+ if it does not recognise the option. */
+
int
c_decode_option (argc, argv)
int argc ATTRIBUTE_UNUSED;
@@ -609,14 +462,12 @@ c_decode_option (argc, argv)
{
int strings_processed;
char *p = argv[0];
-#if USE_CPPLIB
- strings_processed = cpp_handle_option (&parse_in, argc, argv);
-#else
- strings_processed = 0;
-#endif /* ! USE_CPPLIB */
+
+ 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;
}
@@ -646,37 +497,44 @@ c_decode_option (argc, argv)
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];
+ 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_isoc9x = 0;
+ flag_noniso_default_format_attributes = 0;
+ flag_isoc99 = 0;
}
else if (!strcmp (argstart, "iso9899:199409"))
{
- /* ??? The changes since ISO C 1990 are not supported. */
- goto iso_1990;
+ flag_isoc94 = 1;
+ goto iso_1994;
}
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_noniso_default_format_attributes = 0;
+ flag_isoc99 = 1;
+ flag_isoc94 = 1;
}
else if (!strcmp (argstart, "gnu89"))
{
@@ -684,15 +542,19 @@ c_decode_option (argc, argv)
flag_writable_strings = 0;
flag_no_asm = 0;
flag_no_nonansi_builtin = 0;
- flag_isoc9x = 0;
+ flag_noniso_default_format_attributes = 1;
+ flag_isoc99 = 0;
+ 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_noniso_default_format_attributes = 1;
+ flag_isoc99 = 1;
+ flag_isoc94 = 1;
}
else
error ("unknown C standard `%s'", argstart);
@@ -725,6 +587,10 @@ c_decode_option (argc, argv)
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"))
@@ -741,6 +607,10 @@ c_decode_option (argc, argv)
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"))
@@ -757,7 +627,7 @@ c_decode_option (argc, argv)
{
warn_implicit_int = 1;
if (mesg_implicit_function_declaration != 2)
- mesg_implicit_function_declaration = 1;
+ mesg_implicit_function_declaration = 1;
}
else if (!strcmp (p, "-Wno-implicit"))
warn_implicit_int = 0, mesg_implicit_function_declaration = 0;
@@ -777,10 +647,12 @@ c_decode_option (argc, argv)
warn_bad_function_cast = 1;
else if (!strcmp (p, "-Wno-bad-function-cast"))
warn_bad_function_cast = 0;
- else if (!strcmp (p, "-Wmissing-noreturn"))
- warn_missing_noreturn = 1;
else if (!strcmp (p, "-Wno-missing-noreturn"))
warn_missing_noreturn = 0;
+ else if (!strcmp (p, "-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"))
@@ -809,10 +681,28 @@ c_decode_option (argc, argv)
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"))
- warn_format = 1;
+ set_Wformat (1);
else if (!strcmp (p, "-Wno-format"))
- warn_format = 0;
+ 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"))
@@ -829,6 +719,10 @@ c_decode_option (argc, argv)
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"))
; /* cpp handles this one. */
else if (!strcmp (p, "-Wno-comment"))
@@ -861,10 +755,18 @@ c_decode_option (argc, argv)
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, "-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"))
/* Set to greater than 1, so that even unknown pragmas in system
headers will be warned about. */
@@ -881,11 +783,12 @@ c_decode_option (argc, argv)
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;
+ set_Wformat (1);
warn_char_subscripts = 1;
warn_parentheses = 1;
+ warn_sequence_point = 1;
warn_missing_braces = 1;
/* We set this to 2 here, but 1 in -Wmain, so -ffreestanding can turn
it off only if it's not explicit. */
@@ -899,26 +802,8 @@ c_decode_option (argc, argv)
return 1;
}
-/* Hooks for print_node. */
-
-void
-print_lang_decl (file, node, indent)
- FILE *file ATTRIBUTE_UNUSED;
- tree node ATTRIBUTE_UNUSED;
- int indent ATTRIBUTE_UNUSED;
-{
-}
-
void
-print_lang_type (file, node, indent)
- FILE *file ATTRIBUTE_UNUSED;
- tree node ATTRIBUTE_UNUSED;
- int indent ATTRIBUTE_UNUSED;
-{
-}
-
-void
-print_lang_identifier (file, node, indent)
+c_print_identifier (file, node, indent)
FILE *file;
tree node;
int indent;
@@ -929,11 +814,19 @@ print_lang_identifier (file, node, indent)
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));
+ }
}
/* Hook called at end of compilation to assume 1 elt
- for a top-level array decl that wasn't complete before. */
-
+ for a top-level tentative array defn that wasn't complete before. */
+
void
finish_incomplete_decl (decl)
tree decl;
@@ -943,10 +836,10 @@ finish_incomplete_decl (decl)
tree type = TREE_TYPE (decl);
if (type != error_mark_node
&& TREE_CODE (type) == ARRAY_TYPE
+ && ! DECL_EXTERNAL (decl)
&& TYPE_DOMAIN (type) == 0)
{
- if (! DECL_EXTERNAL (decl))
- warning_with_decl (decl, "array `%s' assumed to have one element");
+ warning_with_decl (decl, "array `%s' assumed to have one element");
complete_array_type (type, NULL_TREE, 1);
@@ -957,8 +850,7 @@ finish_incomplete_decl (decl)
/* Create a new `struct binding_level'. */
-static
-struct binding_level *
+static struct binding_level *
make_binding_level ()
{
/* NOSTRICT */
@@ -1020,7 +912,7 @@ void
pushlevel (tag_transparent)
int tag_transparent;
{
- register struct binding_level *newlevel = NULL_BINDING_LEVEL;
+ struct binding_level *newlevel = NULL_BINDING_LEVEL;
/* If this is the top level of a function,
just make sure that NAMED_LABELS is 0. */
@@ -1059,7 +951,7 @@ pushlevel (tag_transparent)
keep_next_if_subblocks = 0;
}
-/* Clear the limbo values of all identifiers defined in BLOCK or a subblock. */
+/* Clear the limbo values of all identifiers defined in BLOCK or a subblock. */
static void
clear_limbo_values (block)
@@ -1074,7 +966,7 @@ clear_limbo_values (block)
for (tem = BLOCK_SUBBLOCKS (block); tem; tem = TREE_CHAIN (tem))
clear_limbo_values (tem);
}
-
+
/* Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered.
@@ -1096,7 +988,7 @@ poplevel (keep, reverse, functionbody)
int reverse;
int functionbody;
{
- register tree link;
+ tree link;
/* The chain of decls was accumulated in reverse order.
Put it into forward order, just for cleanliness. */
tree decls;
@@ -1113,7 +1005,7 @@ poplevel (keep, reverse, functionbody)
#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);
@@ -1163,14 +1055,14 @@ poplevel (keep, reverse, functionbody)
if (DECL_ABSTRACT_ORIGIN (decl) != 0
&& DECL_ABSTRACT_ORIGIN (decl) != decl)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
- else if (DECL_SAVED_INSNS (decl) != 0)
- {
- push_function_context ();
- output_inline_function (decl);
- pop_function_context ();
- }
}
+ /* We used to warn about unused variables in expand_end_bindings,
+ i.e. while generating RTL. But in function-at-a-time mode we may
+ choose to never expand a function at all (e.g. auto inlining), so
+ we do this explicitly now. */
+ warn_about_unused_variables (getdecls ());
+
/* If there were any declarations or structure tags in that level,
or if this level is a function body,
create a BLOCK to record them for the life of this function. */
@@ -1185,9 +1077,7 @@ poplevel (keep, reverse, functionbody)
if (block != 0)
{
BLOCK_VARS (block) = decls;
- BLOCK_TYPE_TAGS (block) = tags;
BLOCK_SUBBLOCKS (block) = subblocks;
- remember_end_note (block);
}
/* In each subblock, record that this is its superior. */
@@ -1241,7 +1131,7 @@ poplevel (keep, reverse, functionbody)
for (link = named_labels; link; link = TREE_CHAIN (link))
{
- register tree label = TREE_VALUE (link);
+ tree label = TREE_VALUE (link);
if (DECL_INITIAL (label) == 0)
{
@@ -1250,7 +1140,7 @@ poplevel (keep, reverse, functionbody)
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;
@@ -1264,7 +1154,7 @@ poplevel (keep, reverse, functionbody)
/* Pop the current level, and free the structure for reuse. */
{
- register struct binding_level *level = current_binding_level;
+ struct binding_level *level = current_binding_level;
current_binding_level = current_binding_level->level_chain;
level->level_chain = free_binding_level;
@@ -1277,8 +1167,8 @@ poplevel (keep, reverse, functionbody)
else if (block)
{
if (!block_previously_created)
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, block);
+ current_binding_level->blocks
+ = chainon (current_binding_level->blocks, block);
}
/* If we did not make a block for the level just exited,
any blocks made for inner levels
@@ -1301,8 +1191,7 @@ poplevel (keep, reverse, functionbody)
cases, the TYPE_CONTEXTs of the relevant tagged type nodes get set
in `grokdeclarator' as soon as we have created the FUNCTION_TYPE
node which will represent the "scope" for these "parameter list local"
- tagged types.
- */
+ tagged types. */
if (functionbody)
for (link = tags; link; link = TREE_CHAIN (link))
@@ -1313,31 +1202,8 @@ poplevel (keep, reverse, functionbody)
if (block)
TREE_USED (block) = 1;
- return block;
-}
-/* Delete the node BLOCK from the current binding level.
- This is used for the block inside a stmt expr ({...})
- so that the block can be reinserted where appropriate. */
-
-void
-delete_block (block)
- tree block;
-{
- tree t;
- if (current_binding_level->blocks == block)
- current_binding_level->blocks = TREE_CHAIN (block);
- for (t = current_binding_level->blocks; t;)
- {
- if (TREE_CHAIN (t) == block)
- TREE_CHAIN (t) = TREE_CHAIN (block);
- else
- t = TREE_CHAIN (t);
- }
- TREE_CHAIN (block) = NULL;
- /* Clear TREE_USED which is always set by poplevel.
- The flag is set again if insert_block is called. */
- TREE_USED (block) = 0;
+ return block;
}
/* Insert BLOCK at the end of the list of subblocks of the
@@ -1358,15 +1224,19 @@ insert_block (block)
void
set_block (block)
- register tree 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 ()
{
- register struct binding_level *newlevel;
+ struct binding_level *newlevel;
/* Reuse or create a struct for this binding level. */
@@ -1394,7 +1264,7 @@ push_label_level ()
void
pop_label_level ()
{
- register struct binding_level *level = label_level_chain;
+ struct binding_level *level = label_level_chain;
tree link, prev;
/* Clear out the definitions of the declared labels in this level.
@@ -1411,8 +1281,8 @@ pop_label_level ()
define_label (input_filename, lineno,
DECL_NAME (TREE_VALUE (link)));
}
- else if (warn_unused && !TREE_USED (TREE_VALUE (link)))
- warning_with_decl (TREE_VALUE (link),
+ 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;
@@ -1456,7 +1326,7 @@ void
pushtag (name, type)
tree name, type;
{
- register struct binding_level *b;
+ struct binding_level *b;
/* Find the proper binding level for this type tag. */
@@ -1471,10 +1341,7 @@ pushtag (name, type)
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
@@ -1503,7 +1370,7 @@ pushtag (name, type)
static int
duplicate_decls (newdecl, olddecl, different_binding_level)
- register tree newdecl, olddecl;
+ tree newdecl, olddecl;
int different_binding_level;
{
int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
@@ -1513,9 +1380,44 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
tree newtype = TREE_TYPE (newdecl);
int errmsg = 0;
- if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
- DECL_MACHINE_ATTRIBUTES (newdecl)
- = merge_machine_decl_attributes (olddecl, newdecl);
+ if (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)))
+ /* Already warned elsewhere. */;
+ else if (DECL_DECLARED_INLINE_P (olddecl)
+ && DECL_UNINLINABLE (olddecl)
+ && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+ /* Already warned. */;
+ 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)
@@ -1553,7 +1455,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
"built-in function `%s' declared as non-function");
else
warning_with_decl (newdecl,
- "built-in function `%s' declared as non-function");
+ "built-in function `%s' declared as non-function");
}
else
{
@@ -1597,35 +1499,26 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
}
else if (!types_match)
{
- /* Accept the return type of the new declaration if same modes. */
+ /* Accept the return type of the new declaration if same modes. */
tree oldreturntype = TREE_TYPE (oldtype);
tree newreturntype = TREE_TYPE (newtype);
- /* Make sure we put the new type in the same obstack as the old ones.
- If the old types are not both in the same obstack, use the
- permanent one. */
- if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
- push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
- else
+ if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
{
- push_obstacks_nochange ();
- end_temporary_allocation ();
- }
-
- if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
- {
/* Function types may be shared, so we can't just modify
the return type of olddecl's function type. */
tree trytype
= build_function_type (newreturntype,
TYPE_ARG_TYPES (oldtype));
-
+ trytype = build_type_attribute_variant (trytype,
+ TYPE_ATTRIBUTES (oldtype));
+
types_match = comptypes (newtype, trytype);
if (types_match)
oldtype = trytype;
}
/* Accept harmless mismatch in first argument type also.
- This is for ffs. */
+ This is for the ffs and fprintf builtins. */
if (TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0
&& TYPE_ARG_TYPES (oldtype) != 0
&& TREE_VALUE (TYPE_ARG_TYPES (newtype)) != 0
@@ -1637,18 +1530,18 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
the return type of olddecl's function type. */
tree trytype
= build_function_type (TREE_TYPE (oldtype),
- tree_cons (NULL_TREE,
+ tree_cons (NULL_TREE,
TREE_VALUE (TYPE_ARG_TYPES (newtype)),
TREE_CHAIN (TYPE_ARG_TYPES (oldtype))));
-
- types_match = comptypes (newtype, trytype);
+ 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;
-
- pop_obstacks ();
}
if (!types_match)
{
@@ -1728,24 +1621,23 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
&& DECL_INITIAL (newdecl) == 0)))
{
/* Classify the problem further. */
- register tree t = TYPE_ARG_TYPES (oldtype);
+ tree t = TYPE_ARG_TYPES (oldtype);
if (t == 0)
t = TYPE_ARG_TYPES (newtype);
for (; t; t = TREE_CHAIN (t))
{
- register tree type = TREE_VALUE (t);
+ 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.");
+ error ("a parameter list with an ellipsis can't match an empty parameter name list declaration");
break;
}
- if (TYPE_MAIN_VARIANT (type) == float_type_node
- || C_PROMOTING_INTEGER_TYPE_P (type))
+ 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.");
+ error ("an argument type that has a default promotion can't match an empty parameter name list declaration");
break;
}
}
@@ -1779,11 +1671,11 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
: "`%s' previously declared here"));
}
else if (TREE_CODE (newdecl) == TYPE_DECL
- && (DECL_IN_SYSTEM_HEADER (olddecl)
+ && (DECL_IN_SYSTEM_HEADER (olddecl)
|| DECL_IN_SYSTEM_HEADER (newdecl)))
{
warning_with_decl (newdecl, "redefinition of `%s'");
- warning_with_decl
+ warning_with_decl
(olddecl,
((DECL_INITIAL (olddecl)
&& current_binding_level == global_binding_level)
@@ -1796,8 +1688,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
&& TYPE_ARG_TYPES (newtype) != 0
&& TYPE_ACTUAL_ARG_TYPES (oldtype) != 0)
{
- register tree type, parm;
- register int nargs;
+ tree type, parm;
+ int nargs;
/* Prototype decl follows defn w/o prototype. */
for (parm = TYPE_ACTUAL_ARG_TYPES (oldtype),
@@ -1816,7 +1708,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
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 (newdecl,
+ "prototype for `%s' follows and number of arguments doesn't match");
error_with_decl (olddecl, "non-prototype definition here");
errmsg = 1;
break;
@@ -1845,12 +1738,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
/* Warn if function is now inline
but was previously declared not inline and has been called. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
- && ! DECL_INLINE (olddecl) && DECL_INLINE (newdecl)
+ && ! 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_INLINE (olddecl) && DECL_INLINE (newdecl)
+ && ! DECL_DECLARED_INLINE_P (olddecl)
+ && DECL_DECLARED_INLINE_P (newdecl)
&& DECL_INITIAL (olddecl) != 0)
warning_with_decl (newdecl,
"`%s' declared inline after its definition");
@@ -1863,8 +1758,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
warning_with_decl (newdecl, "static declaration for `%s' follows non-static");
/* If warn_traditional, warn when a non-static function
- declaration follows a static one. */
- if (warn_traditional
+ declaration follows a static one. */
+ if (warn_traditional && !in_system_header
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& !TREE_PUBLIC (olddecl)
&& TREE_PUBLIC (newdecl))
@@ -1912,26 +1807,21 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
different_binding_level is true. */
tree write_olddecl = different_binding_level ? newdecl : olddecl;
- /* Make sure we put the new type in the same obstack as the old ones.
- If the old types are not both in the same obstack, use the permanent
- one. */
- if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
- push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
- else
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- }
-
/* Merge the data types specified in the two decls. */
if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
{
if (different_binding_level)
- TREE_TYPE (newdecl)
- = build_type_attribute_variant
- (newtype,
- merge_attributes (TYPE_ATTRIBUTES (newtype),
- TYPE_ATTRIBUTES (oldtype)));
+ {
+ 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)
@@ -1952,25 +1842,39 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
{
/* 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);
+ COPY_DECL_RTL (olddecl, newdecl);
/* 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);
}
@@ -2004,18 +1908,18 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
+ /* Copy the assembler name.
+ Currently, it can only be defined in the prototype. */
+ 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);
- DECL_NO_CHECK_MEMORY_USAGE (newdecl)
- |= DECL_NO_CHECK_MEMORY_USAGE (olddecl);
}
-
- pop_obstacks ();
}
/* If cannot merge, then use the new type and qualifiers,
and don't preserve the old rtl. */
@@ -2028,7 +1932,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
}
/* Merge the storage class information. */
- DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);
+ DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);
/* For functions, static overrides non-static. */
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
@@ -2044,8 +1948,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
}
if (DECL_EXTERNAL (newdecl))
{
- TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
- DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
+ if (! different_binding_level)
+ {
+ /* Don't mess with these flags on local externs; they remain
+ external even if there's a declaration at file scope which
+ isn't. */
+ TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
+ DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
+ }
/* An extern decl does not override previous storage class. */
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
if (! DECL_EXTERNAL (newdecl))
@@ -2057,14 +1967,32 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
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 we're redefining a function previously defined as extern
+ inline, make sure we emit debug info for the inline before we
+ throw it away, in case it was inlined into a function that hasn't
+ been written out yet. */
+ if (new_is_definition && DECL_INITIAL (olddecl) && TREE_USED (olddecl))
+ {
+ (*debug_hooks->outlining_inline_function) (olddecl);
+
+ /* The new defn must not be inline. */
+ DECL_INLINE (newdecl) = 0;
+ DECL_UNINLINABLE (newdecl) = 1;
+ }
+ else
+ {
+ /* If either decl says `inline', this fn is inline,
+ unless its definition was passed already. */
+ 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))
{
/* Get rid of any built-in function if new arg types don't match it
@@ -2074,20 +2002,19 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
if (! different_binding_level)
{
TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
- DECL_BUILT_IN (olddecl) = 0;
+ DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
}
}
else
{
/* If redeclaring a builtin function, and not a definition,
it stays built in. */
- DECL_BUILT_IN (newdecl) = 1;
+ DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
}
}
+
/* Also preserve various other info from the definition. */
- else if (! new_is_definition)
- DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
if (! new_is_definition)
{
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
@@ -2097,44 +2024,111 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
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 (newdecl))
- DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ORIGIN (olddecl);
- }
- }
- if (different_binding_level)
- {
- /* Don't output a duplicate symbol or debugging information for this
- declaration.
- Do not set TREE_ASM_WRITTEN for a FUNCTION_DECL since we may actually
- just have two declarations without a definition. VAR_DECLs may need
- the same treatment, I'm not sure. */
- if (TREE_CODE (newdecl) == FUNCTION_DECL)
- DECL_IGNORED_P (newdecl) = 1;
+ /* Set DECL_INLINE on the declaration if we've got a body
+ from which to instantiate. */
+ 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
- TREE_ASM_WRITTEN (newdecl) = DECL_IGNORED_P (newdecl) = 1;
- return 0;
+ {
+ /* If a previous declaration said inline, mark the
+ definition as inlinable. */
+ if (DECL_DECLARED_INLINE_P (newdecl)
+ && ! DECL_UNINLINABLE (newdecl))
+ DECL_INLINE (newdecl) = 1;
+ }
}
+ if (different_binding_level)
+ return 0;
/* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
But preserve OLDDECL's DECL_UID. */
{
- register unsigned olddecl_uid = DECL_UID (olddecl);
+ unsigned olddecl_uid = DECL_UID (olddecl);
- bcopy ((char *) newdecl + sizeof (struct tree_common),
- (char *) olddecl + sizeof (struct tree_common),
- sizeof (struct tree_decl) - sizeof (struct tree_common));
+ 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;
}
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
- DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
+ DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
return 1;
}
+/* Check whether decl-node X shadows an existing declaration.
+ OLDLOCAL is the old IDENTIFIER_LOCAL_VALUE of the DECL_NAME of X,
+ which might be a NULL_TREE. */
+static void
+warn_if_shadowing (x, oldlocal)
+ tree x, oldlocal;
+{
+ tree name;
+
+ if (DECL_EXTERNAL (x))
+ return;
+
+ name = DECL_NAME (x);
+
+ /* Warn if shadowing an argument at the top level of the body. */
+ if (oldlocal != 0
+ /* This warning doesn't apply to the parms of a nested fcn. */
+ && ! current_binding_level->parm_flag
+ /* Check that this is one level down from the parms. */
+ && current_binding_level->level_chain->parm_flag
+ /* Check that the decl being shadowed
+ comes from the parm level, one level up. */
+ && chain_member (oldlocal, current_binding_level->level_chain->names))
+ {
+ if (TREE_CODE (oldlocal) == PARM_DECL)
+ pedwarn ("declaration of `%s' shadows a parameter",
+ IDENTIFIER_POINTER (name));
+ else
+ pedwarn ("declaration of `%s' shadows a symbol from the parameter list",
+ IDENTIFIER_POINTER (name));
+ }
+ /* Maybe warn if shadowing something else. */
+ else if (warn_shadow
+ /* No shadow warnings for internally generated vars. */
+ && DECL_SOURCE_LINE (x) != 0
+ /* No shadow warnings for vars made for inlining. */
+ && ! DECL_FROM_INLINE (x))
+ {
+ if (TREE_CODE (x) == PARM_DECL
+ && current_binding_level->level_chain->parm_flag)
+ /* Don't warn about the parm names in function declarator
+ within a function declarator.
+ It would be nice to avoid warning in any function
+ declarator in a declaration, as opposed to a definition,
+ but there is no way to tell it's not a definition. */
+ ;
+ else if (oldlocal)
+ {
+ 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));
+ }
+}
+
/* Record a decl-node X as belonging to the current lexical scope.
Check for errors (such as an incompatible declaration for the same
name already seen in the same scope).
@@ -2147,37 +2141,43 @@ tree
pushdecl (x)
tree x;
{
- register tree t;
- register tree name = DECL_NAME (x);
- register struct binding_level *b = current_binding_level;
+ tree t;
+ tree name = DECL_NAME (x);
+ struct binding_level *b = current_binding_level;
+
+ /* Functions need the lang_decl data. */
+ if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
+ DECL_LANG_SPECIFIC (x) = (struct lang_decl *)
+ ggc_alloc_cleared (sizeof (struct lang_decl));
DECL_CONTEXT (x) = current_function_decl;
/* A local extern declaration for a function doesn't constitute nesting.
A local auto declaration does, since it's a forward decl
for a nested function coming later. */
- if (TREE_CODE (x) == FUNCTION_DECL && DECL_INITIAL (x) == 0
- && DECL_EXTERNAL (x))
+ if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
+ && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
DECL_CONTEXT (x) = 0;
- if (warn_nested_externs && DECL_EXTERNAL (x) && b != global_binding_level
- && x != IDENTIFIER_IMPLICIT_DECL (name)
- /* Don't print error messages for __FUNCTION__ and __PRETTY_FUNCTION__ */
- && !DECL_IN_SYSTEM_HEADER (x))
- warning ("nested extern declaration of `%s'", IDENTIFIER_POINTER (name));
-
if (name)
{
- char *file;
- int line;
int different_binding_level = 0;
+ if (warn_nested_externs
+ && DECL_EXTERNAL (x)
+ && b != global_binding_level
+ && x != IDENTIFIER_IMPLICIT_DECL (name)
+ /* No error messages for __FUNCTION__ and __PRETTY_FUNCTION__. */
+ && !DECL_IN_SYSTEM_HEADER (x))
+ warning ("nested extern declaration of `%s'",
+ IDENTIFIER_POINTER (name));
+
t = lookup_name_current_level (name);
/* Don't type check externs here when -traditional. This is so that
code with conflicting declarations inside blocks will get warnings
not errors. X11 for instance depends on this. */
if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional)
{
- t = IDENTIFIER_GLOBAL_VALUE (name);
+ t = lookup_name (name);
/* Type decls at global scope don't conflict with externs declared
inside lexical blocks. */
if (t && TREE_CODE (t) == TYPE_DECL)
@@ -2191,12 +2191,6 @@ pushdecl (x)
error_with_decl (x, "`%s' used prior to declaration");
}
- if (t != 0)
- {
- file = DECL_SOURCE_FILE (t);
- line = DECL_SOURCE_LINE (t);
- }
-
/* If this decl is `static' and an implicit decl was seen previously,
warn. But don't complain if -traditional,
since traditional compilers don't complain. */
@@ -2275,22 +2269,23 @@ pushdecl (x)
on a standard type by checking the current value of lineno. */
if (TREE_CODE (x) == TYPE_DECL)
- {
- if (DECL_SOURCE_LINE (x) == 0)
- {
+ {
+ 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
+ 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);
+ {
+ tree tt = TREE_TYPE (x);
DECL_ORIGINAL_TYPE (x) = tt;
- tt = build_type_copy (tt);
- TYPE_NAME (tt) = x;
- TREE_TYPE (x) = tt;
- }
- }
+ tt = build_type_copy (tt);
+ TYPE_NAME (tt) = x;
+ TREE_USED (tt) = TREE_USED (x);
+ TREE_TYPE (x) = tt;
+ }
+ }
/* Multiple external decls of the same identifier ought to match.
Check against both global declarations (when traditional) and out of
@@ -2298,7 +2293,8 @@ pushdecl (x)
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;
@@ -2348,7 +2344,7 @@ pushdecl (x)
{
if (type == error_mark_node)
break;
- if (! TREE_PERMANENT (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,
@@ -2374,7 +2370,7 @@ pushdecl (x)
if (b == global_binding_level)
{
/* Install a global value. */
-
+
/* If the first global decl has external linkage,
warn if we later see static one. */
if (IDENTIFIER_GLOBAL_VALUE (name) == 0 && TREE_PUBLIC (x))
@@ -2435,15 +2431,17 @@ pushdecl (x)
/* 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_DECLARED_INLINE_P (x))
{
/* We have one. Their types must agree. */
if (! comptypes (TREE_TYPE (x),
@@ -2453,22 +2451,25 @@ pushdecl (x)
{
/* Inner extern decl is inline if global one is.
Copy enough to really inline it. */
- if (DECL_INLINE (oldglobal))
+ 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_FRAME_SIZE (x) = DECL_FRAME_SIZE (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_ORIGIN (oldglobal);
+ DECL_ABSTRACT_ORIGIN (x)
+ = DECL_ABSTRACT_ORIGIN (oldglobal);
}
/* Inner extern decl is built-in if global one is. */
if (DECL_BUILT_IN (oldglobal))
{
- DECL_BUILT_IN (x) = DECL_BUILT_IN (oldglobal);
+ DECL_BUILT_IN_CLASS (x) = DECL_BUILT_IN_CLASS (oldglobal);
DECL_FUNCTION_CODE (x) = DECL_FUNCTION_CODE (oldglobal);
}
/* Keep the arg types from a file-scope fcn defn. */
@@ -2479,7 +2480,8 @@ pushdecl (x)
}
}
-#if 0 /* This case is probably sometimes the right thing to do. */
+#if 0
+ /* This case is probably sometimes the right thing to do. */
/* If we have a local external declaration,
then any file-scope declaration should not
have been static. */
@@ -2498,7 +2500,7 @@ pushdecl (x)
&& TREE_PUBLIC (x))
{
if (oldglobal == 0)
- TREE_PUBLIC (name) = 1;
+ TREE_PUBLIC (name) = 1;
/* Save this decl, so that we can do type checking against
other decls after it falls out of scope.
@@ -2511,49 +2513,7 @@ pushdecl (x)
IDENTIFIER_LIMBO_VALUE (name) = x;
}
- /* Warn if shadowing an argument at the top level of the body. */
- if (oldlocal != 0 && !DECL_EXTERNAL (x)
- /* This warning doesn't apply to the parms of a nested fcn. */
- && ! current_binding_level->parm_flag
- /* Check that this is one level down from the parms. */
- && current_binding_level->level_chain->parm_flag
- /* Check that the decl being shadowed
- comes from the parm level, one level up. */
- && chain_member (oldlocal, current_binding_level->level_chain->names))
- {
- if (TREE_CODE (oldlocal) == PARM_DECL)
- pedwarn ("declaration of `%s' shadows a parameter",
- IDENTIFIER_POINTER (name));
- else
- pedwarn ("declaration of `%s' shadows a symbol from the parameter list",
- IDENTIFIER_POINTER (name));
- }
-
- /* Maybe warn if shadowing something else. */
- else if (warn_shadow && !DECL_EXTERNAL (x)
- /* No shadow warnings for internally generated vars. */
- && DECL_SOURCE_LINE (x) != 0
- /* No shadow warnings for vars made for inlining. */
- && ! DECL_FROM_INLINE (x))
- {
- char *id = IDENTIFIER_POINTER (name);
-
- if (TREE_CODE (x) == PARM_DECL
- && current_binding_level->level_chain->parm_flag)
- /* Don't warn about the parm names in function declarator
- within a function declarator.
- It would be nice to avoid warning in any function
- declarator in a declaration, as opposed to a definition,
- but there is no way to tell it's not a definition. */
- ;
- else if (oldlocal != 0 && TREE_CODE (oldlocal) == PARM_DECL)
- warning ("declaration of `%s' shadows a parameter", id);
- else if (oldlocal != 0)
- warning ("declaration of `%s' shadows previous local", id);
- else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
- && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
- warning ("declaration of `%s' shadows global declaration", id);
- }
+ warn_if_shadowing (x, oldlocal);
/* If storing a local value, there may already be one (inherited).
If so, record it for restoration when this binding level ends. */
@@ -2561,9 +2521,21 @@ pushdecl (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)
- ++b->n_incomplete;
+ /* 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)))
+ {
+ 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->n_incomplete;
+ }
}
/* Put decls on list in reverse order.
@@ -2580,8 +2552,8 @@ tree
pushdecl_top_level (x)
tree x;
{
- register tree t;
- register struct binding_level *b = current_binding_level;
+ tree t;
+ struct binding_level *b = current_binding_level;
current_binding_level = global_binding_level;
t = pushdecl (x);
@@ -2596,21 +2568,19 @@ tree
implicitly_declare (functionid)
tree functionid;
{
- register tree decl;
+ tree decl;
int traditional_warning = 0;
/* Only one "implicit declaration" warning per identifier. */
int implicit_warning;
- /* Save the decl permanently so we can warn if definition follows. */
- push_obstacks_nochange ();
- end_temporary_allocation ();
-
/* We used to reuse an old implicit decl here,
but this loses with inline functions because it can clobber
the saved decl chains. */
-/* if (IDENTIFIER_IMPLICIT_DECL (functionid) != 0)
+#if 0
+ if (IDENTIFIER_IMPLICIT_DECL (functionid) != 0)
decl = IDENTIFIER_IMPLICIT_DECL (functionid);
- else */
+ else
+#endif
decl = build_decl (FUNCTION_DECL, functionid, default_function_type);
/* Warn of implicit decl following explicit local extern decl.
@@ -2635,17 +2605,10 @@ implicitly_declare (functionid)
/* This is a no-op in c-lang.c or something real in objc-actions.c. */
maybe_objc_check_decl (decl);
- rest_of_decl_compilation (decl, NULL_PTR, 0, 0);
+ rest_of_decl_compilation (decl, NULL, 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));
@@ -2655,11 +2618,23 @@ implicitly_declare (functionid)
gen_aux_info_record (decl, 0, 1, 0);
- pop_obstacks ();
+ /* Possibly apply some default attributes to this implicit declaration. */
+ decl_attributes (&decl, NULL_TREE, 0);
return decl;
}
+void
+implicit_decl_warning (id)
+ tree id;
+{
+ const 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.
@@ -2680,7 +2655,7 @@ redeclaration_error_message (newdecl, olddecl)
is equivalent to what this code used to do before the build_type_copy
call. The variant type distinction should not matter for traditional
code, because it doesn't have type qualifiers. */
- if (flag_traditional
+ 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))
@@ -2696,12 +2671,13 @@ redeclaration_error_message (newdecl, olddecl)
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_DECLARED_INLINE_P (olddecl) && DECL_EXTERNAL (olddecl)
+ && ! (DECL_DECLARED_INLINE_P (newdecl)
+ && DECL_EXTERNAL (newdecl))))
return 1;
return 0;
}
- else if (current_binding_level == global_binding_level)
+ else if (DECL_CONTEXT (newdecl) == NULL_TREE)
{
/* Objects declared at top level: */
/* If at least one is a reference, it's ok. */
@@ -2740,7 +2716,7 @@ tree
lookup_label (id)
tree id;
{
- register tree decl = IDENTIFIER_LABEL_VALUE (id);
+ tree decl = IDENTIFIER_LABEL_VALUE (id);
if (current_function_decl == 0)
{
@@ -2761,9 +2737,6 @@ lookup_label (id)
decl = build_decl (LABEL_DECL, id, void_type_node);
- /* Make sure every label has an rtx. */
- label_rtx (decl);
-
/* A label not explicitly declared must be local to where it's ref'd. */
DECL_CONTEXT (decl) = current_function_decl;
@@ -2793,18 +2766,18 @@ tree
shadow_label (name)
tree name;
{
- register tree decl = IDENTIFIER_LABEL_VALUE (name);
+ tree decl = IDENTIFIER_LABEL_VALUE (name);
if (decl != 0)
{
- register tree dup;
+ tree dup;
/* Check to make sure that the label hasn't already been declared
at this label scope */
for (dup = named_labels; dup; dup = TREE_CHAIN (dup))
if (TREE_VALUE (dup) == decl)
{
- error ("duplicate label declaration `%s'",
+ error ("duplicate label declaration `%s'",
IDENTIFIER_POINTER (name));
error_with_decl (TREE_VALUE (dup),
"this is a previous declaration");
@@ -2825,7 +2798,7 @@ shadow_label (name)
tree
define_label (filename, line, name)
- char *filename;
+ const char *filename;
int line;
tree name;
{
@@ -2839,9 +2812,15 @@ define_label (filename, line, name)
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 ("duplicate label `%s'", IDENTIFIER_POINTER (name));
+ error_with_file_and_line (filename, line, "duplicate label `%s'",
+ IDENTIFIER_POINTER (name));
return 0;
}
else
@@ -2911,11 +2890,12 @@ lookup_tag (code, name, binding_level, thislevel_only)
tree name;
int thislevel_only;
{
- register struct binding_level *level;
+ struct binding_level *level;
+ int thislevel = 1;
for (level = binding_level; level; level = level->level_chain)
{
- register tree tail;
+ tree tail;
for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
{
if (TREE_PURPOSE (tail) == name)
@@ -2926,12 +2906,22 @@ lookup_tag (code, name, binding_level, thislevel_only)
pending_invalid_xref = name;
pending_invalid_xref_file = input_filename;
pending_invalid_xref_line = lineno;
+ /* If in the same binding level as a declaration as a tag
+ of a different type, this must not be allowed to
+ shadow that tag, so give the error immediately.
+ (For example, "struct foo; union foo;" is invalid.) */
+ if (thislevel)
+ pending_xref_error ();
}
return TREE_VALUE (tail);
}
}
- if (thislevel_only && ! level->tag_transparent)
- return NULL_TREE;
+ if (! level->tag_transparent)
+ {
+ if (thislevel_only)
+ return NULL_TREE;
+ thislevel = 0;
+ }
}
return NULL_TREE;
}
@@ -2959,11 +2949,11 @@ static tree
lookup_tag_reverse (type)
tree type;
{
- register struct binding_level *level;
+ struct binding_level *level;
for (level = current_binding_level; level; level = level->level_chain)
{
- register tree tail;
+ tree tail;
for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
{
if (TREE_VALUE (tail) == type)
@@ -2982,7 +2972,8 @@ tree
lookup_name (name)
tree name;
{
- register tree val;
+ tree val;
+
if (current_binding_level != global_binding_level
&& IDENTIFIER_LOCAL_VALUE (name))
val = IDENTIFIER_LOCAL_VALUE (name);
@@ -2997,7 +2988,7 @@ tree
lookup_name_current_level (name)
tree name;
{
- register tree t;
+ tree t;
if (current_binding_level == global_binding_level)
return IDENTIFIER_GLOBAL_VALUE (name);
@@ -3012,600 +3003,184 @@ lookup_name_current_level (name)
return t;
}
+/* Mark ARG for GC. */
+
+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);
+ }
+}
+
/* Create the predefined scalar types of C,
and some nodes representing standard constants (0, 1, (void *) 0).
Initialize the global binding level.
Make definitions for built-in primitive functions. */
void
-init_decl_processing ()
+c_init_decl_processing ()
{
- register tree endlink;
- /* Either char* or void*. */
- tree traditional_ptr_type_node;
- /* Data types of memcpy and strlen. */
- tree memcpy_ftype, memset_ftype, strlen_ftype;
- tree void_ftype_any, ptr_ftype_void, ptr_ftype_ptr;
- int wchar_type_size;
- tree temp;
- tree array_domain_type;
+ tree endlink;
+ tree ptr_ftype_void, ptr_ftype_ptr;
+
+ /* Adds some ggc roots, and reserved words for c-parse.in. */
+ c_parse_init ();
current_function_decl = NULL;
named_labels = NULL;
current_binding_level = NULL_BINDING_LEVEL;
free_binding_level = NULL_BINDING_LEVEL;
- pushlevel (0); /* make the binding_level structure for global names */
- global_binding_level = current_binding_level;
-
- /* Define `int' and `char' first so that dbx will output them first. */
-
- integer_type_node = make_signed_type (INT_TYPE_SIZE);
- pushdecl (build_decl (TYPE_DECL, ridpointers[(int) RID_INT],
- integer_type_node));
-
- /* Define `char', which is like either `signed char' or `unsigned char'
- but not the same as either. */
-
- char_type_node
- = (flag_signed_char
- ? make_signed_type (CHAR_TYPE_SIZE)
- : make_unsigned_type (CHAR_TYPE_SIZE));
- pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
- char_type_node));
-
- long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
- long_integer_type_node));
-
- unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
- unsigned_type_node));
-
- long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
- long_unsigned_type_node));
-
- long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
- long_long_integer_type_node));
-
- long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
- long_long_unsigned_type_node));
-
- short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
- short_integer_type_node));
-
- short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
- short_unsigned_type_node));
-
- /* `unsigned long' is the standard type for sizeof.
- Traditionally, use a signed type.
- Note that stddef.h uses `unsigned long',
- and this must agree, even if long and int are the same size. */
- set_sizetype
- (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
- if (flag_traditional && TREE_UNSIGNED (sizetype))
- set_sizetype (signed_type (sizetype));
-
- ptrdiff_type_node
- = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
-
- error_mark_node = make_node (ERROR_MARK);
- TREE_TYPE (error_mark_node) = error_mark_node;
-
- /* Define both `signed char' and `unsigned char'. */
- signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
- signed_char_type_node));
-
- unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
- unsigned_char_type_node));
-
- intQI_type_node = make_signed_type (GET_MODE_BITSIZE (QImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node));
-
- intHI_type_node = make_signed_type (GET_MODE_BITSIZE (HImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intHI_type_node));
-
- intSI_type_node = make_signed_type (GET_MODE_BITSIZE (SImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node));
-
- intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
-
-#if HOST_BITS_PER_WIDE_INT >= 64
- intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node));
-#endif
-
- unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
- unsigned_intHI_type_node = make_unsigned_type (GET_MODE_BITSIZE (HImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intHI_type_node));
-
- unsigned_intSI_type_node = make_unsigned_type (GET_MODE_BITSIZE (SImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node));
-
- unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
-
-#if HOST_BITS_PER_WIDE_INT >= 64
- unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node));
-#endif
+ /* Make the binding_level structure for global names. */
+ pushlevel (0);
+ global_binding_level = current_binding_level;
- float_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
- pushdecl (build_decl (TYPE_DECL, ridpointers[(int) RID_FLOAT],
- float_type_node));
- layout_type (float_type_node);
+ build_common_tree_nodes (flag_signed_char);
- double_type_node = make_node (REAL_TYPE);
- if (flag_short_double)
- TYPE_PRECISION (double_type_node) = FLOAT_TYPE_SIZE;
- else
- TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
- pushdecl (build_decl (TYPE_DECL, ridpointers[(int) RID_DOUBLE],
- double_type_node));
- layout_type (double_type_node);
-
- long_double_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
- pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
- long_double_type_node));
- layout_type (long_double_type_node);
-
- complex_integer_type_node = make_node (COMPLEX_TYPE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
- complex_integer_type_node));
- TREE_TYPE (complex_integer_type_node) = integer_type_node;
- layout_type (complex_integer_type_node);
-
- complex_float_type_node = make_node (COMPLEX_TYPE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
- complex_float_type_node));
- TREE_TYPE (complex_float_type_node) = float_type_node;
- layout_type (complex_float_type_node);
-
- complex_double_type_node = make_node (COMPLEX_TYPE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
- complex_double_type_node));
- TREE_TYPE (complex_double_type_node) = double_type_node;
- layout_type (complex_double_type_node);
-
- complex_long_double_type_node = make_node (COMPLEX_TYPE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
- complex_long_double_type_node));
- TREE_TYPE (complex_long_double_type_node) = long_double_type_node;
- layout_type (complex_long_double_type_node);
-
- wchar_type_node
- = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WCHAR_TYPE)));
- wchar_type_size = TYPE_PRECISION (wchar_type_node);
- signed_wchar_type_node = signed_type (wchar_type_node);
- unsigned_wchar_type_node = unsigned_type (wchar_type_node);
-
- integer_zero_node = build_int_2 (0, 0);
- TREE_TYPE (integer_zero_node) = integer_type_node;
- integer_one_node = build_int_2 (1, 0);
- TREE_TYPE (integer_one_node) = integer_type_node;
+ c_common_nodes_and_builtins ();
boolean_type_node = integer_type_node;
boolean_true_node = integer_one_node;
boolean_false_node = integer_zero_node;
- size_zero_node = build_int_2 (0, 0);
- TREE_TYPE (size_zero_node) = sizetype;
- size_one_node = build_int_2 (1, 0);
- TREE_TYPE (size_one_node) = sizetype;
-
- void_type_node = make_node (VOID_TYPE);
- pushdecl (build_decl (TYPE_DECL,
- ridpointers[(int) RID_VOID], void_type_node));
- layout_type (void_type_node); /* Uses integer_zero_node */
- /* We are not going to have real types in C with less than byte alignment,
- so we might as well not have any types that claim to have it. */
- TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
-
- null_pointer_node = build_int_2 (0, 0);
- TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
- layout_type (TREE_TYPE (null_pointer_node));
-
- string_type_node = build_pointer_type (char_type_node);
- const_string_type_node
- = build_pointer_type (build_type_variant (char_type_node, 1, 0));
-
- /* Make a type to be the domain of a few array types
- whose domains don't really matter.
- 200 is small enough that it always fits in size_t
- and large enough that it can hold most function names for the
- initializations of __FUNCTION__ and __PRETTY_FUNCTION__. */
- array_domain_type = build_index_type (build_int_2 (200, 0));
-
- /* make a type for arrays of characters.
- With luck nothing will ever really depend on the length of this
- array type. */
- char_array_type_node
- = build_array_type (char_type_node, array_domain_type);
- /* Likewise for arrays of ints. */
- int_array_type_node
- = build_array_type (integer_type_node, array_domain_type);
- /* This is for wide string constants. */
- wchar_array_type_node
- = build_array_type (wchar_type_node, array_domain_type);
-
- default_function_type
- = build_function_type (integer_type_node, NULL_TREE);
-
- ptr_type_node = build_pointer_type (void_type_node);
- const_ptr_type_node
- = build_pointer_type (build_type_variant (void_type_node, 1, 0));
-
- endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
-
- void_ftype_any
- = build_function_type (void_type_node, NULL_TREE);
-
- float_ftype_float
- = build_function_type (float_type_node,
- tree_cons (NULL_TREE, float_type_node, endlink));
-
- double_ftype_double
- = build_function_type (double_type_node,
- tree_cons (NULL_TREE, double_type_node, endlink));
-
- ldouble_ftype_ldouble
- = build_function_type (long_double_type_node,
- tree_cons (NULL_TREE, long_double_type_node,
- endlink));
-
- double_ftype_double_double
- = build_function_type (double_type_node,
- tree_cons (NULL_TREE, double_type_node,
- tree_cons (NULL_TREE,
- double_type_node, endlink)));
-
- int_ftype_int
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, integer_type_node, endlink));
-
- long_ftype_long
- = build_function_type (long_integer_type_node,
- tree_cons (NULL_TREE,
- long_integer_type_node, endlink));
-
- void_ftype_ptr_ptr_int
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
-
- int_ftype_cptr_cptr_sizet
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, const_ptr_type_node,
- tree_cons (NULL_TREE, const_ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink))));
-
- void_ftype_ptr_int_int
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
-
- string_ftype_ptr_ptr /* strcpy prototype */
- = build_function_type (string_type_node,
- tree_cons (NULL_TREE, string_type_node,
- tree_cons (NULL_TREE,
- const_string_type_node,
- endlink)));
-
- int_ftype_string_string /* strcmp prototype */
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, const_string_type_node,
- tree_cons (NULL_TREE,
- const_string_type_node,
- endlink)));
-
- strlen_ftype /* strlen prototype */
- = build_function_type (flag_traditional ? integer_type_node : sizetype,
- tree_cons (NULL_TREE, const_string_type_node,
- endlink));
-
- traditional_ptr_type_node
- = (flag_traditional ? string_type_node : ptr_type_node);
-
- memcpy_ftype /* memcpy prototype */
- = build_function_type (traditional_ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, const_ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink))));
-
- memset_ftype /* memset prototype */
- = build_function_type (traditional_ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink))));
-
+ /* With GCC, C99's _Bool is always of size 1. */
+ c_bool_type_node = make_unsigned_type (CHAR_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));
- builtin_function ("__builtin_constant_p", default_function_type,
- BUILT_IN_CONSTANT_P, NULL_PTR);
-
- builtin_function ("__builtin_return_address",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- unsigned_type_node,
- endlink)),
- BUILT_IN_RETURN_ADDRESS, NULL_PTR);
-
- builtin_function ("__builtin_frame_address",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- unsigned_type_node,
- endlink)),
- BUILT_IN_FRAME_ADDRESS, NULL_PTR);
-
- builtin_function ("__builtin_aggregate_incoming_address",
- build_function_type (ptr_type_node, NULL_TREE),
- BUILT_IN_AGGREGATE_INCOMING_ADDRESS, NULL_PTR);
-
- /* Hooks for the DWARF 2 __throw routine. */
- builtin_function ("__builtin_unwind_init",
- build_function_type (void_type_node, endlink),
- BUILT_IN_UNWIND_INIT, NULL_PTR);
- builtin_function ("__builtin_dwarf_cfa", ptr_ftype_void,
- BUILT_IN_DWARF_CFA, NULL_PTR);
- builtin_function ("__builtin_dwarf_fp_regnum",
- build_function_type (unsigned_type_node, endlink),
- BUILT_IN_DWARF_FP_REGNUM, NULL_PTR);
- builtin_function ("__builtin_dwarf_reg_size", int_ftype_int,
- BUILT_IN_DWARF_REG_SIZE, NULL_PTR);
- builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
- BUILT_IN_FROB_RETURN_ADDR, NULL_PTR);
- builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
- BUILT_IN_EXTRACT_RETURN_ADDR, NULL_PTR);
- builtin_function
- ("__builtin_eh_return",
- build_function_type (void_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE,
- type_for_mode (ptr_mode, 0),
- tree_cons (NULL_TREE,
- ptr_type_node,
- endlink)))),
- BUILT_IN_EH_RETURN, NULL_PTR);
-
- builtin_function ("__builtin_alloca",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink)),
- BUILT_IN_ALLOCA, "alloca");
- builtin_function ("__builtin_ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR);
- /* Define alloca, ffs as builtins.
- Declare _exit just to mark it as volatile. */
- if (! flag_no_builtin && !flag_no_nonansi_builtin)
- {
- temp = builtin_function ("alloca",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink)),
- BUILT_IN_ALLOCA, NULL_PTR);
- /* Suppress error if redefined as a non-function. */
- DECL_BUILT_IN_NONANSI (temp) = 1;
- temp = builtin_function ("ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR);
- /* Suppress error if redefined as a non-function. */
- DECL_BUILT_IN_NONANSI (temp) = 1;
- temp = builtin_function ("_exit", void_ftype_any, NOT_BUILT_IN,
- NULL_PTR);
- TREE_THIS_VOLATILE (temp) = 1;
- TREE_SIDE_EFFECTS (temp) = 1;
- /* Suppress error if redefined as a non-function. */
- DECL_BUILT_IN_NONANSI (temp) = 1;
- }
-
- builtin_function ("__builtin_abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR);
- builtin_function ("__builtin_fabsf", float_ftype_float, BUILT_IN_FABS,
- NULL_PTR);
- builtin_function ("__builtin_fabs", double_ftype_double, BUILT_IN_FABS,
- NULL_PTR);
- builtin_function ("__builtin_fabsl", ldouble_ftype_ldouble, BUILT_IN_FABS,
- NULL_PTR);
- builtin_function ("__builtin_labs", long_ftype_long, BUILT_IN_LABS,
- NULL_PTR);
- builtin_function ("__builtin_saveregs",
- build_function_type (ptr_type_node, NULL_TREE),
- BUILT_IN_SAVEREGS, NULL_PTR);
-/* EXPAND_BUILTIN_VARARGS is obsolete. */
-#if 0
- builtin_function ("__builtin_varargs",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink)),
- BUILT_IN_VARARGS, NULL_PTR);
-#endif
- builtin_function ("__builtin_classify_type", default_function_type,
- BUILT_IN_CLASSIFY_TYPE, NULL_PTR);
- builtin_function ("__builtin_next_arg",
- build_function_type (ptr_type_node, NULL_TREE),
- BUILT_IN_NEXT_ARG, NULL_PTR);
- builtin_function ("__builtin_args_info",
- build_function_type (integer_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink)),
- BUILT_IN_ARGS_INFO, NULL_PTR);
-
- /* Untyped call and return. */
- builtin_function ("__builtin_apply_args",
- build_function_type (ptr_type_node, NULL_TREE),
- BUILT_IN_APPLY_ARGS, NULL_PTR);
-
- temp = tree_cons (NULL_TREE,
- build_pointer_type (build_function_type (void_type_node,
- NULL_TREE)),
- tree_cons (NULL_TREE,
- ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink)));
- builtin_function ("__builtin_apply",
- build_function_type (ptr_type_node, temp),
- BUILT_IN_APPLY, NULL_PTR);
- builtin_function ("__builtin_return",
- build_function_type (void_type_node,
- tree_cons (NULL_TREE,
- ptr_type_node,
- endlink)),
- BUILT_IN_RETURN, NULL_PTR);
-
- /* Currently under experimentation. */
- builtin_function ("__builtin_memcpy", memcpy_ftype,
- BUILT_IN_MEMCPY, "memcpy");
- builtin_function ("__builtin_memcmp", int_ftype_cptr_cptr_sizet,
- BUILT_IN_MEMCMP, "memcmp");
- builtin_function ("__builtin_memset", memset_ftype,
- BUILT_IN_MEMSET, "memset");
- builtin_function ("__builtin_strcmp", int_ftype_string_string,
- BUILT_IN_STRCMP, "strcmp");
- builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr,
- BUILT_IN_STRCPY, "strcpy");
- builtin_function ("__builtin_strlen", strlen_ftype,
- BUILT_IN_STRLEN, "strlen");
- builtin_function ("__builtin_sqrtf", float_ftype_float,
- BUILT_IN_FSQRT, "sqrtf");
- builtin_function ("__builtin_fsqrt", double_ftype_double,
- BUILT_IN_FSQRT, "sqrt");
- builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
- BUILT_IN_FSQRT, "sqrtl");
- builtin_function ("__builtin_sinf", float_ftype_float,
- BUILT_IN_SIN, "sinf");
- builtin_function ("__builtin_sin", double_ftype_double,
- BUILT_IN_SIN, "sin");
- builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
- BUILT_IN_SIN, "sinl");
- builtin_function ("__builtin_cosf", float_ftype_float,
- BUILT_IN_COS, "cosf");
- builtin_function ("__builtin_cos", double_ftype_double,
- BUILT_IN_COS, "cos");
- builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
- BUILT_IN_COS, "cosl");
- builtin_function ("__builtin_setjmp",
- build_function_type (integer_type_node,
- tree_cons (NULL_TREE,
- ptr_type_node, endlink)),
- BUILT_IN_SETJMP, NULL_PTR);
- builtin_function ("__builtin_longjmp",
- build_function_type
- (void_type_node,
- tree_cons (NULL, ptr_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))),
- BUILT_IN_LONGJMP, NULL_PTR);
- builtin_function ("__builtin_trap",
- build_function_type (void_type_node, endlink),
- BUILT_IN_TRAP, NULL_PTR);
-
- /* In an ANSI C program, it is okay to supply built-in meanings
- for these functions, since applications cannot validly use them
- with any other meaning.
- However, honor the -fno-builtin option. */
- if (!flag_no_builtin)
- {
- builtin_function ("abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR);
- builtin_function ("fabsf", float_ftype_float, BUILT_IN_FABS, NULL_PTR);
- builtin_function ("fabs", double_ftype_double, BUILT_IN_FABS, NULL_PTR);
- builtin_function ("fabsl", ldouble_ftype_ldouble, BUILT_IN_FABS,
- NULL_PTR);
- builtin_function ("labs", long_ftype_long, BUILT_IN_LABS, NULL_PTR);
- builtin_function ("memcpy", memcpy_ftype, BUILT_IN_MEMCPY, NULL_PTR);
- builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP,
- NULL_PTR);
- builtin_function ("memset", memset_ftype, BUILT_IN_MEMSET, NULL_PTR);
- builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP,
- NULL_PTR);
- builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY,
- NULL_PTR);
- builtin_function ("strlen", strlen_ftype, BUILT_IN_STRLEN, NULL_PTR);
- builtin_function ("sqrtf", float_ftype_float, BUILT_IN_FSQRT, NULL_PTR);
- builtin_function ("sqrt", double_ftype_double, BUILT_IN_FSQRT, NULL_PTR);
- builtin_function ("sqrtl", ldouble_ftype_ldouble, BUILT_IN_FSQRT,
- NULL_PTR);
- builtin_function ("sinf", float_ftype_float, BUILT_IN_SIN, NULL_PTR);
- builtin_function ("sin", double_ftype_double, BUILT_IN_SIN, NULL_PTR);
- builtin_function ("sinl", ldouble_ftype_ldouble, BUILT_IN_SIN, NULL_PTR);
- builtin_function ("cosf", float_ftype_float, BUILT_IN_COS, NULL_PTR);
- builtin_function ("cos", double_ftype_double, BUILT_IN_COS, NULL_PTR);
- builtin_function ("cosl", ldouble_ftype_ldouble, BUILT_IN_COS, NULL_PTR);
-
- /* Declare these functions volatile
- to avoid spurious "control drops through" warnings. */
- /* Don't specify the argument types, to avoid errors
- from certain code which isn't valid in ANSI but which exists. */
- temp = builtin_function ("abort", void_ftype_any, NOT_BUILT_IN,
- NULL_PTR);
- TREE_THIS_VOLATILE (temp) = 1;
- TREE_SIDE_EFFECTS (temp) = 1;
- temp = builtin_function ("exit", void_ftype_any, NOT_BUILT_IN, NULL_PTR);
- TREE_THIS_VOLATILE (temp) = 1;
- TREE_SIDE_EFFECTS (temp) = 1;
+ /* 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 0
- /* Support for these has not been written in either expand_builtin
- or build_function_call. */
- builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, NULL_PTR);
- builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, NULL_PTR);
- builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR,
- NULL_PTR);
- builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL,
- NULL_PTR);
- builtin_function ("__builtin_fmod", double_ftype_double_double,
- BUILT_IN_FMOD, NULL_PTR);
- builtin_function ("__builtin_frem", double_ftype_double_double,
- BUILT_IN_FREM, NULL_PTR);
- builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP,
- NULL_PTR);
- builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN,
- NULL_PTR);
-#endif
+ 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;
- /* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */
- declare_function_name ();
+ make_fname_decl = c_make_fname_decl;
+ start_fname_decls ();
- start_identifier_warnings ();
+ incomplete_decl_finalize_hook = finish_incomplete_decl;
- /* Prepare to check format strings against argument lists. */
- init_function_format_info ();
+ /* Record our roots. */
+
+ 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 (&current_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);
+}
- init_iterators ();
+/* 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 is wrong for C99's __func__. FIXME. */
- incomplete_decl_finalize_hook = finish_incomplete_decl;
+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);
+ /* We don't push the decl, so have to set its context here. */
+ 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;
- lang_get_alias_set = c_get_alias_set;
+ TREE_USED (decl) = 1;
+
+ finish_decl (decl, init, NULL_TREE);
+
+ return decl;
}
/* Return a definition for a builtin function named NAME and whose data type
@@ -3617,10 +3192,11 @@ init_decl_processing ()
the name to be called if we can't opencode the function. */
tree
-builtin_function (name, type, function_code, library_name)
+builtin_function (name, type, function_code, class, library_name)
const char *name;
tree type;
- enum built_in_function function_code;
+ int function_code;
+ enum built_in_class class;
const char *library_name;
{
tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
@@ -3632,21 +3208,34 @@ builtin_function (name, type, function_code, library_name)
if (flag_traditional && name[0] != '_')
DECL_BUILT_IN_NONANSI (decl) = 1;
if (library_name)
- DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
- make_decl_rtl (decl, NULL_PTR, 1);
+ SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
+ make_decl_rtl (decl, NULL);
pushdecl (decl);
- if (function_code != NOT_BUILT_IN)
- {
- DECL_BUILT_IN (decl) = 1;
- DECL_FUNCTION_CODE (decl) = function_code;
- }
+ DECL_BUILT_IN_CLASS (decl) = class;
+ DECL_FUNCTION_CODE (decl) = function_code;
+
/* Warn if a function in the namespace for users
is used without an occasion to consider it declared. */
if (name[0] != '_' || name[1] != '_')
C_DECL_ANTICIPATED (decl) = 1;
+ /* Possibly apply some default attributes to this built-in function. */
+ decl_attributes (&decl, NULL_TREE, 0);
+
return decl;
}
+
+/* Apply default attributes to a function, if a system function with default
+ attributes. */
+
+void
+insert_default_attributes (decl)
+ tree decl;
+{
+ if (!TREE_PUBLIC (decl))
+ return;
+ c_common_insert_default_attributes (decl);
+}
/* Called when a declaration is seen that contains no names to declare.
If its type is a reference to a structure, union or enum inherited
@@ -3671,7 +3260,7 @@ shadow_tag_warned (declspecs, warned)
no pedwarn. */
{
int found_tag = 0;
- register tree link;
+ tree link;
tree specs, attrs;
pending_invalid_xref = 0;
@@ -3682,15 +3271,15 @@ shadow_tag_warned (declspecs, warned)
for (link = specs; link; link = TREE_CHAIN (link))
{
- register tree value = TREE_VALUE (link);
- register enum tree_code code = TREE_CODE (value);
+ tree value = TREE_VALUE (link);
+ enum tree_code code = TREE_CODE (value);
if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
/* Used to test also that TYPE_SIZE (value) != 0.
That caused warning for `struct foo;' at top level in the file. */
{
- register tree name = lookup_tag_reverse (value);
- register tree t;
+ tree name = lookup_tag_reverse (value);
+ tree t;
found_tag++;
@@ -3734,17 +3323,80 @@ shadow_tag_warned (declspecs, warned)
}
}
+/* Construct an array declarator. EXPR is the expression inside [], or
+ NULL_TREE. QUALS are the type qualifiers inside the [] (to be applied
+ to the pointer to which a parameter array is converted). STATIC_P is
+ non-zero if "static" is inside the [], zero otherwise. VLA_UNSPEC_P
+ is non-zero is the array is [*], a VLA of unspecified length which is
+ nevertheless a complete type (not currently implemented by GCC),
+ zero otherwise. The declarator is constructed as an ARRAY_REF
+ (to be decoded by grokdeclarator), whose operand 0 is what's on the
+ left of the [] (filled by in set_array_declarator_type) and operand 1
+ is the expression inside; whose TREE_TYPE is the type qualifiers and
+ which has TREE_STATIC set if "static" is used. */
+
+tree
+build_array_declarator (expr, quals, static_p, vla_unspec_p)
+ tree expr;
+ tree quals;
+ int static_p;
+ int vla_unspec_p;
+{
+ tree decl;
+ decl = build_nt (ARRAY_REF, NULL_TREE, expr);
+ TREE_TYPE (decl) = quals;
+ TREE_STATIC (decl) = (static_p ? 1 : 0);
+ if (pedantic && !flag_isoc99)
+ {
+ if (static_p || quals != NULL_TREE)
+ pedwarn ("ISO C89 does not support `static' or type qualifiers in parameter array declarators");
+ if (vla_unspec_p)
+ pedwarn ("ISO C89 does not support `[*]' array declarators");
+ }
+ if (vla_unspec_p)
+ warning ("GCC does not yet properly implement `[*]' array declarators");
+ return decl;
+}
+
+/* Set the type of an array declarator. DECL is the declarator, as
+ constructed by build_array_declarator; TYPE is what appears on the left
+ of the [] and goes in operand 0. ABSTRACT_P is non-zero if it is an
+ abstract declarator, zero otherwise; this is used to reject static and
+ type qualifiers in abstract declarators, where they are not in the
+ C99 grammar. */
+
+tree
+set_array_declarator_type (decl, type, abstract_p)
+ tree decl;
+ tree type;
+ int abstract_p;
+{
+ TREE_OPERAND (decl, 0) = type;
+ if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
+ error ("static or type qualifiers in abstract declarator");
+ return decl;
+}
+
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
tree
groktypename (typename)
tree typename;
{
+ tree specs, attrs;
+
if (TREE_CODE (typename) != TREE_LIST)
return typename;
- return grokdeclarator (TREE_VALUE (typename),
- TREE_PURPOSE (typename),
- TYPENAME, 0);
+
+ split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
+
+ typename = grokdeclarator (TREE_VALUE (typename), specs, TYPENAME, 0,
+ NULL_TREE);
+
+ /* Apply attributes. */
+ decl_attributes (&typename, attrs, 0);
+
+ return typename;
}
/* Return a PARM_DECL node for a given pair of specs and declarator. */
@@ -3757,7 +3409,7 @@ groktypename_in_parm_context (typename)
return typename;
return grokdeclarator (TREE_VALUE (typename),
TREE_PURPOSE (typename),
- PARM, 0);
+ PARM, 0, NULL_TREE);
}
/* Decode a declarator in an ordinary declaration or data definition.
@@ -3775,26 +3427,27 @@ groktypename_in_parm_context (typename)
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)
+start_decl (declarator, declspecs, initialized, attributes)
tree declarator, declspecs;
int initialized;
- tree attributes, prefix_attributes;
+ tree attributes;
{
- register tree decl = grokdeclarator (declarator, declspecs,
- NORMAL, initialized);
- register tree tem;
- int init_written = initialized;
+ tree decl;
+ tree tem;
+
+ /* An object declared as __attribute__((deprecated)) suppresses
+ warnings of uses of other deprecated items. */
+ if (lookup_attribute ("deprecated", attributes))
+ deprecated_state = DEPRECATED_SUPPRESS;
- /* The corresponding pop_obstacks is in finish_decl. */
- push_obstacks_nochange ();
+ decl = grokdeclarator (declarator, declspecs,
+ NORMAL, initialized, NULL_TREE);
+
+ deprecated_state = DEPRECATED_NORMAL;
- if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
- && !strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "main"))
+ 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)
@@ -3831,7 +3484,12 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
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)
+
+ /* This can happen if the array size is an undefined macro. We already
+ gave a warning, so we don't need another one. */
+ if (TREE_TYPE (decl) == error_mark_node)
+ initialized = 0;
+ else if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
{
/* A complete type is ok if size is fixed. */
@@ -3848,7 +3506,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
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)));
@@ -3858,7 +3516,8 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
if (initialized)
{
-#if 0 /* Seems redundant with grokdeclarator. */
+#if 0
+ /* Seems redundant with grokdeclarator. */
if (current_binding_level != global_binding_level
&& DECL_EXTERNAL (decl)
&& TREE_CODE (decl) != FUNCTION_DECL)
@@ -3889,12 +3548,15 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
if (! flag_no_common || ! TREE_PUBLIC (decl))
DECL_COMMON (decl) = 1;
-#ifdef SET_DEFAULT_DECL_ATTRIBUTES
- SET_DEFAULT_DECL_ATTRIBUTES (decl, attributes);
-#endif
-
/* Set attributes here so if duplicate decl, will have proper attributes. */
- decl_attributes (decl, attributes, prefix_attributes);
+ decl_attributes (&decl, attributes, 0);
+
+ 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");
/* Add this decl to the current binding level.
TEM may equal DECL or it may be a previous decl of the same name. */
@@ -3905,23 +3567,17 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
/* But not if this is a duplicate decl
and we preserved the rtl from the previous one
(which may or may not happen). */
- && DECL_RTL (tem) == 0)
+ && !DECL_RTL_SET_P (tem)
+ && !DECL_CONTEXT (tem))
{
- if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
+ 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);
}
- 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;
}
@@ -3935,31 +3591,22 @@ finish_decl (decl, init, asmspec_tree)
tree decl, init;
tree asmspec_tree;
{
- register tree type = TREE_TYPE (decl);
+ tree type = TREE_TYPE (decl);
int was_incomplete = (DECL_SIZE (decl) == 0);
- int temporary = allocation_temporary_p ();
- char *asmspec = 0;
+ const char *asmspec = 0;
- /* If a name was specified, get the string. */
+ /* If a name was specified, get the string. */
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
/* If `start_decl' didn't like having an initialization, ignore it now. */
-
if (init != 0 && DECL_INITIAL (decl) == 0)
init = 0;
+
/* Don't crash if parm is initialized. */
if (TREE_CODE (decl) == PARM_DECL)
init = 0;
- if (ITERATOR_P (decl))
- {
- if (init == 0)
- error_with_decl (decl, "iterator has no initial value");
- else
- init = save_expr (init);
- }
-
if (init)
{
if (TREE_CODE (decl) != TYPE_DECL)
@@ -3972,18 +3619,7 @@ finish_decl (decl, init, asmspec_tree)
}
}
- /* Pop back to the obstack that is current for this binding level.
- This is because MAXINDEX, rtl, etc. to be made below
- must go in the permanent obstack. But don't discard the
- temporary data yet. */
- pop_obstacks ();
-#if 0 /* pop_obstacks was near the end; this is what was here. */
- if (current_binding_level == global_binding_level && temporary)
- end_temporary_allocation ();
-#endif
-
/* Deduce size of array from initialization, if not already known */
-
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == 0
&& TREE_CODE (decl) != TYPE_DECL)
@@ -4003,7 +3639,7 @@ finish_decl (decl, init, asmspec_tree)
if (failure == 1)
error_with_decl (decl, "initializer fails to determine size of `%s'");
- if (failure == 2)
+ else if (failure == 2)
{
if (do_default)
error_with_decl (decl, "array size missing in `%s'");
@@ -4020,8 +3656,8 @@ finish_decl (decl, init, asmspec_tree)
/* TYPE_MAX_VALUE is always one less than the number of elements
in the array, because we start counting at zero. Therefore,
warn only if the value is less than zero. */
- if (pedantic && TYPE_DOMAIN (type) != 0
- && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
+ 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);
@@ -4029,11 +3665,13 @@ finish_decl (decl, init, asmspec_tree)
if (TREE_CODE (decl) == VAR_DECL)
{
- if (DECL_SIZE (decl) == 0
- && TYPE_SIZE (TREE_TYPE (decl)) != 0)
+ 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
+ /* Don't give an error if we already gave one earlier. */
+ && TREE_TYPE (decl) != error_mark_node
&& (TREE_STATIC (decl)
?
/* A static variable with an incomplete type
@@ -4041,11 +3679,8 @@ finish_decl (decl, init, asmspec_tree)
Also if it is not file scope.
Otherwise, let it through, but if it is not `extern'
then it may cause an error message later. */
- /* A duplicate_decls call could have changed an extern
- declaration into a file scope one. This can be detected
- by TREE_ASM_WRITTEN being set. */
(DECL_INITIAL (decl) != 0
- || (DECL_CONTEXT (decl) != 0 && ! TREE_ASM_WRITTEN (decl)))
+ || DECL_CONTEXT (decl) != 0)
:
/* An automatic variable with an incomplete type
is an error. */
@@ -4064,7 +3699,7 @@ finish_decl (decl, init, asmspec_tree)
error_with_decl (decl, "storage size of `%s' isn't constant");
}
- if (TREE_USED (type))
+ if (TREE_USED (type))
TREE_USED (decl) = 1;
}
@@ -4072,10 +3707,11 @@ finish_decl (decl, init, asmspec_tree)
builtin any more. Also reset DECL_RTL so we can give it its new
name. */
if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
- {
- DECL_BUILT_IN (decl) = 0;
- DECL_RTL (decl) = 0;
- }
+ {
+ DECL_BUILT_IN_CLASS (decl) = NOT_BUILT_IN;
+ SET_DECL_RTL (decl, NULL_RTX);
+ SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
+ }
/* Output the assembler code and/or RTL code for variables and functions,
unless the type is an undefined structure or union.
@@ -4083,26 +3719,51 @@ finish_decl (decl, init, asmspec_tree)
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
{
- if ((flag_traditional || TREE_PERMANENT (decl))
- && allocation_temporary_p ())
+ /* This is a no-op in c-lang.c or something real in objc-actions.c. */
+ maybe_objc_check_decl (decl);
+
+ if (!DECL_CONTEXT (decl))
{
- 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);
+ if (DECL_INITIAL (decl) == NULL_TREE
+ || DECL_INITIAL (decl) == error_mark_node)
+ /* Don't output anything
+ when a tentative file-scope definition is seen.
+ But at end of compilation, do output code for them. */
+ DECL_DEFER_OUTPUT (decl) = 1;
rest_of_decl_compilation (decl, asmspec,
(DECL_CONTEXT (decl) == 0
- || TREE_ASM_WRITTEN (decl)),
- 0);
- pop_obstacks ();
+ || TREE_ASM_WRITTEN (decl)), 0);
}
else
{
- /* This is a no-op in c-lang.c or something real in objc-actions.c. */
- maybe_objc_check_decl (decl);
- rest_of_decl_compilation (decl, asmspec, DECL_CONTEXT (decl) == 0,
- 0);
+ /* This is a local variable. If there is an ASMSPEC, the
+ user has requested that we handle it specially. */
+ if (asmspec)
+ {
+ /* In conjunction with an ASMSPEC, the `register'
+ keyword indicates that we should place the variable
+ in a particular register. */
+ if (DECL_REGISTER (decl))
+ DECL_C_HARD_REGISTER (decl) = 1;
+
+ /* If this is not a static variable, issue a warning.
+ It doesn't make any sense to give an ASMSPEC for an
+ ordinary, non-register local variable. Historically,
+ GCC has accepted -- but ignored -- the ASMSPEC in
+ this case. */
+ if (TREE_CODE (decl) == VAR_DECL
+ && !DECL_REGISTER (decl)
+ && !TREE_STATIC (decl))
+ warning_with_decl (decl,
+ "ignoring asm-specifier for non-static local variable `%s'");
+ else
+ SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
+ }
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ add_decl_stmt (decl);
}
+
if (DECL_CONTEXT (decl) != 0)
{
/* Recompute the RTL of a local array now
@@ -4115,11 +3776,7 @@ finish_decl (decl, init, asmspec_tree)
/* If it's still incomplete now, no init will save it. */
if (DECL_SIZE (decl) == 0)
DECL_INITIAL (decl) = 0;
- expand_decl (decl);
}
- /* Compute and store the initial value. */
- if (TREE_CODE (decl) != FUNCTION_DECL)
- expand_decl_init (decl);
}
}
@@ -4127,82 +3784,9 @@ finish_decl (decl, init, asmspec_tree)
{
/* 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, 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. */
@@ -4235,13 +3819,10 @@ push_parm_decl (parm)
/* Don't try computing parm sizes now -- wait till fn is called. */
immediate_size_expand = 0;
- /* The corresponding pop_obstacks is in finish_decl. */
- push_obstacks_nochange ();
-
decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
- TREE_PURPOSE (TREE_PURPOSE (parm)), PARM, 0);
- decl_attributes (decl, TREE_VALUE (TREE_VALUE (parm)),
- TREE_PURPOSE (TREE_VALUE (parm)));
+ TREE_PURPOSE (TREE_PURPOSE (parm)),
+ PARM, 0, NULL_TREE);
+ decl_attributes (&decl, TREE_VALUE (parm), 0);
#if 0
if (DECL_NAME (decl))
@@ -4249,7 +3830,8 @@ push_parm_decl (parm)
tree olddecl;
olddecl = lookup_name (DECL_NAME (decl));
if (pedantic && olddecl != 0 && TREE_CODE (olddecl) == TYPE_DECL)
- pedwarn_with_decl (decl, "ANSI C forbids parameter `%s' shadowing typedef");
+ pedwarn_with_decl (decl,
+ "ISO C forbids parameter `%s' shadowing typedef");
}
#endif
@@ -4274,6 +3856,61 @@ clear_parm_order ()
current_binding_level->parm_order = NULL_TREE;
}
+/* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound
+ literal, which may be an incomplete array type completed by the
+ initializer; INIT is a CONSTRUCTOR that initializes the compound
+ literal. */
+
+tree
+build_compound_literal (type, init)
+ tree type;
+ tree init;
+{
+ /* We do not use start_decl here because we have a type, not a declarator;
+ and do not use finish_decl because the decl should be stored inside
+ the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_STMT. */
+ 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))
+ {
+ /* This decl needs a name for the assembler output. We also need
+ a unique suffix to be added to the name, for which DECL_CONTEXT
+ must be set. */
+ 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;
+}
+
/* Make TYPE a complete type based on INITIAL_VALUE.
Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
2 if there was no information (in which case assume 1 if DO_DEFAULT). */
@@ -4284,7 +3921,7 @@ complete_array_type (type, initial_value, do_default)
tree initial_value;
int do_default;
{
- register tree maxindex = NULL_TREE;
+ tree maxindex = NULL_TREE;
int value = 0;
if (initial_value)
@@ -4301,13 +3938,14 @@ complete_array_type (type, initial_value, do_default)
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);
}
@@ -4343,6 +3981,92 @@ complete_array_type (type, initial_value, do_default)
return value;
}
+/* A bit-field NAME should have an integer type whose precision
+ accurately reflects its WIDTH. If TYPE is good for that, return
+ it, otherwise create and return the appropriate type.
+
+ This routine also performs sanity checks on the bit-field's type
+ and width, and uses appropriate values if they are invalid. */
+static tree
+build_bitfield_integer_type (type, width, orig_name)
+ tree type, width;
+ const char *orig_name;
+{
+ tree type_mv;
+ unsigned int max_width;
+ unsigned HOST_WIDE_INT w;
+ const char *name = orig_name ? orig_name: _("<anonymous>");
+
+ /* Necessary? */
+ STRIP_NOPS (width);
+
+ /* Detect and ignore out of range field width and process valid
+ field widths. */
+ if (TREE_CODE (width) != INTEGER_CST)
+ {
+ error ("bit-field `%s' width not an integer constant", name);
+ width = integer_one_node;
+ }
+ else
+ {
+ constant_expression_warning (width);
+ if (tree_int_cst_sgn (width) < 0)
+ {
+ error ("negative width in bit-field `%s'", name);
+ width = integer_one_node;
+ }
+ else if (integer_zerop (width) && orig_name)
+ {
+ error ("zero width for bit-field `%s'", name);
+ width = integer_one_node;
+ }
+ }
+
+ /* Detect invalid bit-field type. */
+ if (TREE_CODE (type) != INTEGER_TYPE
+ && TREE_CODE (type) != BOOLEAN_TYPE
+ && TREE_CODE (type) != ENUMERAL_TYPE)
+ {
+ error ("bit-field `%s' has invalid type", name);
+ type = unsigned_type_node;
+ }
+
+ type_mv = TYPE_MAIN_VARIANT (type);
+ if (pedantic
+ && type_mv != integer_type_node
+ && type_mv != unsigned_type_node
+ && type_mv != c_bool_type_node
+ /* Accept an enum that's equivalent to int or unsigned int. */
+ && (TREE_CODE (type) != ENUMERAL_TYPE
+ || TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node)))
+ pedwarn ("type of bit-field `%s' is a GCC extension", name);
+
+ if (type_mv == c_bool_type_node)
+ max_width = CHAR_TYPE_SIZE;
+ else
+ max_width = TYPE_PRECISION (type);
+
+ if (0 < compare_tree_int (width, max_width))
+ {
+ error ("width of `%s' exceeds its type", name);
+ w = max_width;
+ }
+ else
+ w = tree_low_cst (width, 1);
+
+ if (TREE_CODE (type) == ENUMERAL_TYPE
+ && (w < min_precision (TYPE_MIN_VALUE (type), TREE_UNSIGNED (type))
+ || w < min_precision (TYPE_MAX_VALUE (type), TREE_UNSIGNED (type))))
+ warning ("`%s' is narrower than values of its type", name);
+
+ /* The type of a bit-field should have precision the same as the
+ bit-field's width. */
+ if (w != TYPE_PRECISION (type))
+ type = build_nonstandard_integer_type (w, TREE_UNSIGNED (type));
+
+ return type;
+}
+
/* Given declspecs and a declarator,
determine the name and type of the object declared
and construct a ..._DECL node for it.
@@ -4362,8 +4086,9 @@ complete_array_type (type, initial_value, do_default)
TYPENAME if for a typename (in a cast or sizeof).
Don't make a DECL node; just return the ..._TYPE node.
FIELD for a struct or union field; make a FIELD_DECL.
- BITFIELD for a field with specified width.
INITIALIZED is 1 if the decl has an initializer.
+ WIDTH is non-NULL for bit-fields, and is an INTEGER_CST node representing
+ the width of the bit-field.
In the TYPENAME case, DECLARATOR is really an absolute declarator.
It may also be so in the PARM case, for a prototype where the
@@ -4373,11 +4098,12 @@ complete_array_type (type, initial_value, do_default)
and `extern' are interpreted. */
static tree
-grokdeclarator (declarator, declspecs, decl_context, initialized)
+grokdeclarator (declarator, declspecs, decl_context, initialized, width)
tree declspecs;
tree declarator;
enum decl_context decl_context;
int initialized;
+ tree width;
{
int specbits = 0;
tree spec;
@@ -4392,29 +4118,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
int explicit_char = 0;
int defaulted_int = 0;
tree typedef_decl = 0;
- const char *name;
+ const char *name, *orig_name;
tree typedef_type = 0;
int funcdef_flag = 0;
enum tree_code innermost_code = ERROR_MARK;
- int bitfield = 0;
int size_varies = 0;
- tree decl_machine_attr = NULL_TREE;
-
- if (decl_context == BITFIELD)
- bitfield = 1, decl_context = FIELD;
+ tree decl_attr = NULL_TREE;
+ tree array_ptr_quals = NULL_TREE;
+ int array_parm_static = 0;
+ tree returned_attrs = NULL_TREE;
+ bool bitfield = width != NULL_TREE;
if (decl_context == FUNCDEF)
funcdef_flag = 1, decl_context = NORMAL;
- push_obstacks_nochange ();
-
- if (flag_traditional && allocation_temporary_p ())
- end_temporary_allocation ();
-
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
{
- register tree decl = declarator;
+ tree decl = declarator;
name = 0;
while (decl)
@@ -4427,6 +4148,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
decl = TREE_OPERAND (decl, 0);
break;
+ case TREE_LIST:
+ decl = TREE_VALUE (decl);
+ break;
+
case IDENTIFIER_NODE:
name = IDENTIFIER_POINTER (decl);
decl = 0;
@@ -4435,6 +4160,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
default:
abort ();
}
+ orig_name = name;
if (name == 0)
name = "type name";
}
@@ -4472,49 +4198,62 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
{
- register int i;
- register tree id = TREE_VALUE (spec);
+ tree id = TREE_VALUE (spec);
+
+ /* If the entire declaration is itself tagged as deprecated then
+ suppress reports of deprecated items. */
+ if (id && TREE_DEPRECATED (id))
+ {
+ if (deprecated_state != DEPRECATED_SUPPRESS)
+ warn_deprecated_use (id);
+ }
if (id == ridpointers[(int) RID_INT])
explicit_int = 1;
if (id == ridpointers[(int) RID_CHAR])
explicit_char = 1;
- if (TREE_CODE (id) == IDENTIFIER_NODE)
- for (i = (int) RID_FIRST_MODIFIER; i < (int) RID_MAX; i++)
- {
- if (ridpointers[i] == id)
- {
- if (i == (int) RID_LONG && specbits & (1<<i))
- {
- if (longlong)
- error ("`long long long' is too long for GCC");
- else
- {
- if (pedantic && ! in_system_header && warn_long_long)
- pedwarn ("ANSI C does not support `long long'");
- longlong = 1;
- }
- }
- else if (specbits & (1 << i))
- pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
- specbits |= 1 << i;
- goto found;
- }
- }
+ if (TREE_CODE (id) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (id))
+ {
+ enum rid i = C_RID_CODE (id);
+ 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);
/* Actual typedefs come to us as TYPE_DECL nodes. */
else if (TREE_CODE (id) == TYPE_DECL)
{
- type = TREE_TYPE (id);
- decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
- typedef_decl = id;
+ if (TREE_TYPE (id) == error_mark_node)
+ ; /* Allow the type to default to int to avoid cascading errors. */
+ else
+ {
+ type = TREE_TYPE (id);
+ decl_attr = DECL_ATTRIBUTES (id);
+ typedef_decl = id;
+ }
}
/* Built-in types come as identifiers. */
else if (TREE_CODE (id) == IDENTIFIER_NODE)
{
- register tree t = lookup_name (id);
+ tree t = lookup_name (id);
if (TREE_TYPE (t) == error_mark_node)
;
else if (!t || TREE_CODE (t) != TYPE_DECL)
@@ -4529,7 +4268,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
else if (TREE_CODE (id) != ERROR_MARK)
type = id;
- found: {}
+ found:
+ ;
}
typedef_type = type;
@@ -4543,18 +4283,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
{
if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
| (1 << (int) RID_SIGNED)
- | (1 << (int) RID_UNSIGNED))))
+ | (1 << (int) RID_UNSIGNED)
+ | (1 << (int) RID_COMPLEX))))
/* 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)
+ if ((warn_implicit_int || warn_return_type || flag_isoc99)
+ && 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;
@@ -4569,7 +4312,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
if ((specbits & 1 << (int) RID_LONG) && ! longlong
&& TYPE_MAIN_VARIANT (type) == double_type_node)
{
- specbits &= ~ (1 << (int) RID_LONG);
+ specbits &= ~(1 << (int) RID_LONG);
type = long_double_type_node;
}
@@ -4630,13 +4373,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
&& TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
{
error ("complex invalid for `%s'", name);
- specbits &= ~ (1 << (int) RID_COMPLEX);
+ specbits &= ~(1 << (int) RID_COMPLEX);
}
/* Decide whether an integer type is signed or not.
- Optionally treat bitfields as signed by default. */
+ Optionally treat bit-fields as signed by default. */
if (specbits & 1 << (int) RID_UNSIGNED
- /* Traditionally, all bitfields are unsigned. */
+ /* Traditionally, all bit-fields are unsigned. */
|| (bitfield && flag_traditional
&& (! explicit_flag_signed_bitfields || !flag_signed_bitfields))
|| (bitfield && ! flag_signed_bitfields
@@ -4673,6 +4416,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
if (specbits & 1 << (int) RID_COMPLEX)
{
+ if (pedantic && !flag_isoc99)
+ pedwarn ("ISO C89 does not support complex types");
/* If we just have "complex", it is equivalent to
"complex double", but if any modifiers at all are specified it is
the complex form of TYPE. E.g, "complex short" is
@@ -4682,9 +4427,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
&& ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
| (1 << (int) RID_SIGNED)
| (1 << (int) RID_UNSIGNED))))
- type = complex_double_type_node;
+ {
+ if (pedantic)
+ pedwarn ("ISO C does not support plain `complex' meaning `double complex'");
+ type = complex_double_type_node;
+ }
else if (type == integer_type_node)
- type = complex_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)
@@ -4692,9 +4445,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
else if (type == long_double_type_node)
type = complex_long_double_type_node;
else
- type = build_complex_type (type);
+ {
+ if (pedantic)
+ pedwarn ("ISO C does not support complex integer types");
+ type = build_complex_type (type);
+ }
}
+ /* A bit-field needs its type to have precision equal to its width,
+ rather than the precision of the specified standard type. */
+ if (bitfield)
+ type = build_bitfield_integer_type (type, width, orig_name);
+
/* Figure out the type qualifiers for the declaration. There are
two ways a declaration can become qualified. One is something
like `const int i' where the `const' is explicit. Another is
@@ -4704,11 +4466,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
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);
@@ -4726,7 +4488,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
if (specbits & 1 << (int) RID_EXTERN) nclasses++;
if (specbits & 1 << (int) RID_REGISTER) nclasses++;
if (specbits & 1 << (int) RID_TYPEDEF) nclasses++;
- if (specbits & 1 << (int) RID_ITERATOR) nclasses++;
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
@@ -4746,8 +4507,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
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));
+ specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
+ | (1 << (int) RID_AUTO));
}
else if (decl_context != NORMAL && nclasses > 0)
{
@@ -4755,15 +4516,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
;
else
{
- error ((decl_context == FIELD
- ? "storage class specified for structure field `%s'"
- : (decl_context == PARM
- ? "storage class specified for parameter `%s'"
- : "storage class specified for typename")),
- name);
- specbits &= ~ ((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
- | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
- | (1 << (int) RID_EXTERN));
+ 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)
@@ -4780,18 +4548,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
else if (current_binding_level == global_binding_level
&& specbits & (1 << (int) RID_AUTO))
error ("top-level declaration of `%s' specifies `auto'", name);
- else if ((specbits & 1 << (int) RID_ITERATOR)
- && TREE_CODE (declarator) != IDENTIFIER_NODE)
- {
- error ("iterator `%s' has derived type", name);
- type = error_mark_node;
- }
- else if ((specbits & 1 << (int) RID_ITERATOR)
- && TREE_CODE (type) != INTEGER_TYPE)
- {
- error ("iterator `%s' has noninteger type", name);
- type = error_mark_node;
- }
}
/* Now figure out the structure of the declarator proper.
@@ -4809,6 +4565,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
/* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
an INDIRECT_REF (for *...),
a CALL_EXPR (for ...(...)),
+ a TREE_LIST (for nested attributes),
an identifier (for the name being declared)
or a null pointer (for the place in an absolute declarator
where the name was omitted).
@@ -4820,20 +4577,54 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
array or function or pointer, and DECLARATOR has had its
outermost layer removed. */
- if (TREE_CODE (declarator) == ARRAY_REF)
+ if (array_ptr_quals != NULL_TREE || array_parm_static)
{
- 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));
+ /* Only the innermost declarator (making a parameter be of
+ array type which is converted to pointer type)
+ may have static or type qualifiers. */
+ error ("static or type qualifiers in non-parameter array declarator");
+ array_ptr_quals = NULL_TREE;
+ array_parm_static = 0;
+ }
+
+ if (TREE_CODE (declarator) == TREE_LIST)
+ {
+ /* We encode a declarator with embedded attributes using
+ a TREE_LIST. */
+ tree attrs = TREE_PURPOSE (declarator);
+ tree inner_decl;
+ int attr_flags = 0;
+ declarator = TREE_VALUE (declarator);
+ inner_decl = declarator;
+ while (inner_decl != NULL_TREE
+ && TREE_CODE (inner_decl) == TREE_LIST)
+ inner_decl = TREE_VALUE (inner_decl);
+ if (inner_decl == NULL_TREE
+ || TREE_CODE (inner_decl) == IDENTIFIER_NODE)
+ attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
+ if (TREE_CODE (inner_decl) == CALL_EXPR)
+ attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
+ if (TREE_CODE (inner_decl) == ARRAY_REF)
+ attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
+ returned_attrs = decl_attributes (&type,
+ chainon (returned_attrs, attrs),
+ attr_flags);
+ }
+ else if (TREE_CODE (declarator) == ARRAY_REF)
+ {
+ tree itype = NULL_TREE;
+ tree size = TREE_OPERAND (declarator, 1);
/* The index is a signed object `sizetype' bits wide. */
tree index_type = signed_type (sizetype);
+ array_ptr_quals = TREE_TYPE (declarator);
+ array_parm_static = TREE_STATIC (declarator);
+
declarator = TREE_OPERAND (declarator, 0);
/* Check for some types that there cannot be arrays of. */
- 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;
@@ -4851,12 +4642,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
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. */
@@ -4866,15 +4651,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
STRIP_TYPE_NOPS (size);
- if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE)
+ if (! INTEGRAL_TYPE_P (TREE_TYPE (size)))
{
error ("size of array `%s' has non-integer type", name);
size = integer_one_node;
}
if (pedantic && integer_zerop (size))
- pedwarn ("ANSI C forbids zero-size array `%s'", name);
+ pedwarn ("ISO C forbids zero-size array `%s'", name);
if (TREE_CODE (size) == INTEGER_CST)
{
@@ -4894,52 +4678,74 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
if (pedantic)
{
if (TREE_CONSTANT (size))
- pedwarn ("ANSI C forbids array `%s' whose size can't be evaluated", name);
+ pedwarn ("ISO C89 forbids array `%s' whose size can't be evaluated",
+ name);
else
- pedwarn ("ANSI C forbids variable-size array `%s'", name);
+ pedwarn ("ISO C89 forbids variable-size array `%s'",
+ name);
}
}
- /* Convert size to index_type, so that if it is a variable
- the computations will be done in the proper mode. */
- itype = fold (build (MINUS_EXPR, index_type,
- convert (index_type, size),
- convert (index_type, size_one_node)));
-
- /* If that overflowed, the array is too big.
- ??? While a size of INT_MAX+1 technically shouldn't cause
- an overflow (because we subtract 1), the overflow is recorded
- during the conversion to index_type, before the subtraction.
- Handling this case seems like an unnecessary complication. */
- if (TREE_OVERFLOW (itype))
+ if (integer_zerop (size))
{
- error ("size of array `%s' is too large", name);
- type = error_mark_node;
- continue;
+ /* A zero-length array cannot be represented with an
+ unsigned index type, which is what we'll get with
+ build_index_type. Create an open-ended range instead. */
+ itype = build_range_type (sizetype, size, NULL_TREE);
}
+ else
+ {
+ /* Compute the maximum valid index, that is, size - 1.
+ Do the calculation in index_type, so that if it is
+ a variable the computations will be done in the
+ proper mode. */
+ itype = fold (build (MINUS_EXPR, index_type,
+ convert (index_type, size),
+ convert (index_type, size_one_node)));
+
+ /* If that overflowed, the array is too big.
+ ??? While a size of INT_MAX+1 technically shouldn't
+ cause an overflow (because we subtract 1), the overflow
+ is recorded during the conversion to index_type, before
+ the subtraction. Handling this case seems like an
+ unnecessary complication. */
+ if (TREE_OVERFLOW (itype))
+ {
+ error ("size of array `%s' is too large", name);
+ type = error_mark_node;
+ continue;
+ }
- if (size_varies)
- itype = variable_size (itype);
- itype = build_index_type (itype);
+ if (size_varies)
+ itype = variable_size (itype);
+ itype = build_index_type (itype);
+ }
}
+ else if (decl_context == FIELD)
+ {
+ /* ??? Need to check somewhere that this is a structure
+ and not a union, that this field is last, and that
+ this structure has at least one other named member. */
-#if 0 /* This had bad results for pointers to arrays, as in
- union incomplete (*foo)[4]; */
- /* Complain about arrays of incomplete types, except in typedefs. */
+ if (pedantic && !flag_isoc99 && !in_system_header)
+ pedwarn ("ISO C89 does not support flexible array members");
- if (TYPE_SIZE (type) == 0
- /* Avoid multiple warnings for nested array types. */
- && TREE_CODE (type) != ARRAY_TYPE
- && !(specbits & (1 << (int) RID_TYPEDEF))
- && !C_TYPE_BEING_DEFINED (type))
- warning ("array type has incomplete element type");
-#endif
+ /* ISO C99 Flexible array members are effectively identical
+ to GCC's zero-length array extension. */
+ itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+ }
+
+ /* If pedantic, complain about arrays of incomplete types. */
-#if 0 /* We shouldn't have a function type here at all!
- Functions aren't allowed as array elements. */
+ if (pedantic && !COMPLETE_TYPE_P (type))
+ pedwarn ("array type has incomplete element type");
+
+#if 0
+ /* We shouldn't have a function type here at all!
+ Functions aren't allowed as array elements. */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& (constp || volatilep))
- pedwarn ("ANSI C forbids const or volatile function types");
+ pedwarn ("ISO C forbids const or volatile function types");
#endif
/* Build the array type itself, then merge any constancy or
@@ -4951,18 +4757,27 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
if (type_quals)
type = c_build_qualified_type (type, type_quals);
-#if 0 /* don't clear these; leave them set so that the array type
- or the variable is itself const or volatile. */
- type_quals = TYPE_UNQUALIFIED;
-#endif
-
if (size_varies)
C_TYPE_VARIABLE_SIZE (type) = 1;
+
+ /* The GCC extension for zero-length arrays differs from
+ ISO flexible array members in that sizeof yields zero. */
+ 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)
{
- int extern_ref = (!(specbits & (1 << (int) RID_AUTO))
- || current_binding_level == global_binding_level);
tree arg_types;
/* Declaring a function type.
@@ -4992,12 +4807,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
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. */
@@ -5007,21 +4816,29 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
only for the CALL_EXPR
closest to the identifier. */
&& TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE);
-#if 0 /* This seems to be false. We turn off temporary allocation
- above in this function if -traditional.
- And this code caused inconsistent results with prototypes:
- callers would ignore them, and pass arguments wrong. */
-
- /* Omit the arg types if -traditional, since the arg types
- and the list links might not be permanent. */
- type = build_function_type (type,
- flag_traditional
- ? NULL_TREE : arg_types);
-#endif
/* Type qualifiers before the return type of the function
qualify the return type, not the function type. */
if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ {
+ /* Type qualifiers on a function return type are normally
+ permitted by the standard but have no effect, so give a
+ warning at -W. Qualifiers on a void return type have
+ meaning as a GNU extension, and are banned on function
+ definitions in ISO C. FIXME: strictly we shouldn't
+ pedwarn for qualified void return types except on function
+ definitions, but not doing so could lead to the undesirable
+ state of a "volatile void" function return type not being
+ warned about, and a use of the function being compiled
+ with GNU semantics, with no diagnostics under -pedantic. */
+ 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);
@@ -5032,7 +4849,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
the FUNCTION_TYPE node itself. */
{
- register tree link;
+ tree link;
for (link = last_function_parm_tags;
link;
@@ -5047,7 +4864,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn ("ANSI C forbids qualified function types");
+ pedwarn ("ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
type_quals = TYPE_UNQUALIFIED;
@@ -5060,7 +4877,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
if (TREE_TYPE (declarator))
{
- register tree typemodlist;
+ tree typemodlist;
int erred = 0;
constp = 0;
@@ -5071,23 +4888,28 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
{
tree qualifier = TREE_VALUE (typemodlist);
- if (qualifier == ridpointers[(int) RID_CONST])
- constp++;
- else if (qualifier == ridpointers[(int) RID_VOLATILE])
- volatilep++;
- else if (qualifier == ridpointers[(int) RID_RESTRICT])
- restrictp++;
- else if (!erred)
+ if (C_IS_RESERVED_WORD (qualifier))
{
- erred = 1;
- error ("invalid type modifier within pointer declarator");
+ 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 (constp > 1)
+
+ if (erred)
+ error ("invalid type modifier within pointer declarator");
+ 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)
@@ -5107,9 +4929,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
/* 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);
+ {
+ error ("size of array `%s' is too large", name);
+ /* If we proceed with the array type as it is, we'll eventually
+ crash in tree_low_cst(). */
+ type = error_mark_node;
+ }
/* If this is declaring a typedef name, return a TYPE_DECL. */
@@ -5120,14 +4947,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
in typenames, fields or parameters */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn ("ANSI C forbids qualified function types");
+ 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;
- pop_obstacks ();
+ decl_attributes (&decl, returned_attrs, 0);
return decl;
}
@@ -5138,8 +4965,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
controlled separately by its own initializer. */
if (type != 0 && typedef_type != 0
- && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type)
- && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0)
+ && 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)
@@ -5155,10 +4982,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
in typenames, fields or parameters */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn ("ANSI C forbids const or volatile function types");
+ pedwarn ("ISO C forbids const or volatile function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
- pop_obstacks ();
+ decl_attributes (&type, returned_attrs, 0);
return type;
}
@@ -5168,7 +4995,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
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
@@ -5183,12 +5010,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */
{
- register tree decl;
+ tree decl;
if (decl_context == PARM)
{
- tree type_as_written = type;
- tree main_type;
+ tree type_as_written;
+ tree promoted_type;
/* A parameter declared as an array of T is really a pointer to T.
One declared as a function is really a pointer to a function. */
@@ -5201,17 +5028,59 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
type_quals = TYPE_UNQUALIFIED;
+ if (array_ptr_quals)
+ {
+ tree new_ptr_quals, new_ptr_attrs;
+ int erred = 0;
+ split_specs_attrs (array_ptr_quals, &new_ptr_quals, &new_ptr_attrs);
+ /* We don't yet implement attributes in this context. */
+ if (new_ptr_attrs != NULL_TREE)
+ warning ("attributes in parameter array declarator ignored");
+
+ constp = 0;
+ volatilep = 0;
+ restrictp = 0;
+ for (; new_ptr_quals; new_ptr_quals = TREE_CHAIN (new_ptr_quals))
+ {
+ tree qualifier = TREE_VALUE (new_ptr_quals);
+
+ if (C_IS_RESERVED_WORD (qualifier))
+ {
+ if (C_RID_CODE (qualifier) == RID_CONST)
+ constp++;
+ else if (C_RID_CODE (qualifier) == RID_VOLATILE)
+ volatilep++;
+ else if (C_RID_CODE (qualifier) == RID_RESTRICT)
+ restrictp++;
+ else
+ erred++;
+ }
+ else
+ erred++;
+ }
+
+ if (erred)
+ error ("invalid type modifier within array declarator");
+
+ type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+ | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+ | (volatilep ? TYPE_QUAL_VOLATILE : 0));
+ }
size_varies = 0;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
if (pedantic && type_quals)
- pedwarn ("ANSI C forbids qualified function types");
+ 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)
@@ -5222,37 +5091,28 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
(For example, shorts and chars are passed as ints.)
When there is a prototype, this is overridden later. */
- DECL_ARG_TYPE (decl) = type;
- main_type = (type == error_mark_node
- ? error_mark_node
- : TYPE_MAIN_VARIANT (type));
- if (main_type == float_type_node)
- DECL_ARG_TYPE (decl) = double_type_node;
- /* Don't use TYPE_PRECISION to decide whether to promote,
- because we should convert short if it's the same size as int,
- but we should not convert long if it's the same size as int. */
- else if (TREE_CODE (main_type) != ERROR_MARK
- && C_PROMOTING_INTEGER_TYPE_P (main_type))
+ if (type == error_mark_node)
+ promoted_type = type;
+ else
{
- if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)
- && TREE_UNSIGNED (type))
- DECL_ARG_TYPE (decl) = unsigned_type_node;
- else
- DECL_ARG_TYPE (decl) = integer_type_node;
+ 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)
{
/* Structure field. It may not be a function. */
-
if (TREE_CODE (type) == FUNCTION_TYPE)
{
error ("field `%s' declared as a function", name);
type = build_pointer_type (type);
}
- else if (TREE_CODE (type) != ERROR_MARK && TYPE_SIZE (type) == 0)
+ 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;
@@ -5263,11 +5123,37 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
type_quals),
TYPE_DOMAIN (type));
-#if 0 /* Leave the field const or volatile as well. */
+#if 0
+ /* Leave the field const or volatile as well. */
type_quals = TYPE_UNQUALIFIED;
#endif
}
decl = build_decl (FIELD_DECL, declarator, type);
+ if (bitfield)
+ {
+ DECL_SIZE (decl) = bitsize_int (TYPE_PRECISION (type));
+ DECL_BIT_FIELD (decl) = 1;
+ SET_DECL_C_BIT_FIELD (decl);
+
+ /* Bit-field width 0 => force desired amount of alignment. */
+ if (TYPE_PRECISION (type) == 0)
+ {
+#ifdef EMPTY_FIELD_BOUNDARY
+ DECL_ALIGN (decl) = MAX (DECL_ALIGN (decl),
+ EMPTY_FIELD_BOUNDARY);
+#endif
+#ifdef PCC_BITFIELD_TYPE_MATTERS
+ if (PCC_BITFIELD_TYPE_MATTERS)
+ {
+ DECL_ALIGN (decl) = MAX (DECL_ALIGN (decl),
+ TYPE_ALIGN (type));
+ DECL_USER_ALIGN (decl) |= TYPE_USER_ALIGN (type);
+ }
+#endif
+ }
+ }
+ DECL_NONADDRESSABLE_P (decl) = bitfield;
+
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
}
@@ -5294,28 +5180,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
&& 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);
+ decl = build_decl_attribute_variant (decl, decl_attr);
- if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
- pedwarn ("ANSI C forbids qualified function types");
+ DECL_LANG_SPECIFIC (decl) = (struct lang_decl *)
+ ggc_alloc_cleared (sizeof (struct lang_decl));
- if (pedantic
- && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node
- && TYPE_QUALS (TREE_TYPE (TREE_TYPE (decl)))
- && ! DECL_IN_SYSTEM_HEADER (decl))
- pedwarn ("ANSI C forbids qualified void function return type");
+ if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
+ pedwarn ("ISO C forbids qualified function types");
/* 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)
@@ -5325,16 +5202,34 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
= !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
/* Record presence of `inline', if it is reasonable. */
- if (inlinep)
+ if (MAIN_NAME_P (declarator))
{
- if (! strcmp (IDENTIFIER_POINTER (declarator), "main"))
+ if (inlinep)
warning ("cannot inline function `main'");
- else
- /* Assume that otherwise the function can be inlined. */
- DECL_INLINE (decl) = 1;
-
- if (specbits & (1 << (int) RID_EXTERN))
- current_extern_inline = 1;
+ }
+ else if (inlinep)
+ {
+ /* Assume that otherwise the function can be inlined. */
+ DECL_DECLARED_INLINE_P (decl) = 1;
+
+ /* Do not mark bare declarations as DECL_INLINE. Doing so
+ in the presence of multiple declarations can result in
+ the abstract origin pointing between the declarations,
+ which will confuse dwarf2out. */
+ if (initialized)
+ {
+ DECL_INLINE (decl) = 1;
+ if (specbits & (1 << (int) RID_EXTERN))
+ current_extern_inline = 1;
+ }
+ }
+ /* If -finline-functions, assume it can be inlined. This does
+ two things: let the function be deferred until it is actually
+ needed, and let dwarf2 know that the function is inlinable. */
+ else if (flag_inline_trees == 2 && initialized)
+ {
+ DECL_INLINE (decl) = 1;
+ DECL_DECLARED_INLINE_P (decl) = 0;
}
}
else
@@ -5346,20 +5241,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
/* Move type qualifiers down to element of an array. */
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 /* Leave the variable const or volatile as well. */
type_quals = TYPE_UNQUALIFIED;
#endif
}
-
- /* If this is a block level extern, it must live past the end
- of the function so that we can check it against other
- extern declarations (IDENTIFIER_LIMBO_VALUE). */
- if (extern_ref && allocation_temporary_p ())
- end_temporary_allocation ();
-
+ 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;
@@ -5385,9 +5278,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
-
- if (specbits & 1 << (int) RID_ITERATOR)
- ITERATOR_P (decl) = 1;
}
/* Record `register' declaration for warnings on &
@@ -5405,7 +5295,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
mark_addressable (decl);
- pop_obstacks ();
+ decl_attributes (&decl, returned_attrs, 0);
return decl;
}
@@ -5474,7 +5364,9 @@ grokparms (parms_info, funcdef_flag)
{
/* Barf if the parameter itself has an incomplete type. */
tree type = TREE_VALUE (typelt);
- if (TYPE_SIZE (type) == 0)
+ if (type == error_mark_node)
+ continue;
+ if (!COMPLETE_TYPE_P (type))
{
if (funcdef_flag && DECL_NAME (parm) != 0)
error ("parameter `%s' has incomplete type",
@@ -5487,8 +5379,10 @@ grokparms (parms_info, funcdef_flag)
TREE_TYPE (parm) = error_mark_node;
}
}
-#if 0 /* This has been replaced by parm_tags_warning
- which uses a more accurate criterion for what to warn about. */
+#if 0
+ /* This has been replaced by parm_tags_warning, which
+ uses a more accurate criterion for what to warn
+ about. */
else
{
/* Now warn if is a pointer to an incomplete type. */
@@ -5496,7 +5390,7 @@ grokparms (parms_info, funcdef_flag)
|| 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",
@@ -5509,24 +5403,10 @@ grokparms (parms_info, funcdef_flag)
typelt = TREE_CHAIN (typelt);
}
- /* Allocate the list of types the way we allocate a type. */
- if (first_parm && ! TREE_PERMANENT (first_parm))
- {
- /* Construct a copy of the list of types
- on the saveable obstack. */
- tree result = NULL;
- for (typelt = first_parm; typelt; typelt = TREE_CHAIN (typelt))
- result = saveable_tree_cons (NULL_TREE, TREE_VALUE (typelt),
- result);
- return nreverse (result);
- }
- else
- /* The list we have is permanent already. */
- return first_parm;
+ return first_parm;
}
}
-
/* Return a tree_list node with info on a parameter list just parsed.
The TREE_PURPOSE is a chain of decls of those parms.
The TREE_VALUE is a list of structure, union and enum tags defined.
@@ -5540,29 +5420,36 @@ tree
get_parm_info (void_at_end)
int void_at_end;
{
- register tree decl, t;
- register tree types = 0;
+ 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;
- /* 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.
Likewise any forward parm decls that didn't have real parm decls. */
- for (decl = parms; decl; )
+ for (decl = parms; decl;)
{
tree next = TREE_CHAIN (decl);
@@ -5573,7 +5460,8 @@ get_parm_info (void_at_end)
}
else if (TREE_ASM_WRITTEN (decl))
{
- error_with_decl (decl, "parameter `%s' has just a forward declaration");
+ error_with_decl (decl,
+ "parameter `%s' has just a forward declaration");
TREE_CHAIN (decl) = new_parms;
new_parms = decl;
}
@@ -5605,15 +5493,13 @@ get_parm_info (void_at_end)
args are passed in their declared types. */
tree type = TREE_TYPE (decl);
DECL_ARG_TYPE (decl) = type;
-#ifdef PROMOTE_PROTOTYPES
- if ((TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
+ if (PROMOTE_PROTOTYPES
+ && INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (decl) = integer_type_node;
-#endif
- types = saveable_tree_cons (NULL_TREE, TREE_TYPE (decl), types);
- if (TYPE_MAIN_VARIANT (TREE_VALUE (types)) == void_type_node && ! erred
+ 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");
@@ -5622,10 +5508,10 @@ get_parm_info (void_at_end)
}
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
@@ -5645,20 +5531,30 @@ parmlist_tags_warning ()
if (code == UNION_TYPE && TREE_PURPOSE (elt) == 0 && !pedantic)
continue;
if (TREE_PURPOSE (elt) != 0)
- warning ("`%s %s' declared inside parameter list",
- (code == RECORD_TYPE ? "struct"
- : code == UNION_TYPE ? "union"
- : "enum"),
- IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
+ {
+ 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
- warning ("anonymous %s declared inside parameter list",
- (code == RECORD_TYPE ? "struct"
- : code == UNION_TYPE ? "union"
- : "enum"));
-
+ {
+ /* For translation these need to be separate 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.");
+ warning ("its scope is only this definition or declaration, which is probably not what you want");
already = 1;
}
}
@@ -5672,24 +5568,24 @@ xref_tag (code, name)
enum tree_code code;
tree name;
{
- int temporary = allocation_temporary_p ();
-
/* If a cross reference is requested, look up the type
already defined for this tag and return it. */
- register tree ref = lookup_tag (code, name, current_binding_level, 0);
- /* Even if this is the wrong type of tag, return what we found.
- There will be an error message anyway, from pending_xref_error.
- If we create an empty xref just for an invalid use of the type,
- the main result is to create lots of superfluous error messages. */
- if (ref)
+ tree ref = lookup_tag (code, name, current_binding_level, 0);
+ /* If this is the right type of tag, return what we found.
+ (This reference will be shadowed by shadow_tag later if appropriate.)
+ If this is the wrong type of tag, do not return it. If it was the
+ wrong type in the same binding level, we will have had an error
+ message already; if in a different binding level and declaring
+ a name, pending_xref_error will give an error message; but if in a
+ different binding level and not declaring a name, this tag should
+ shadow the previous declaration of a different type of tag, and
+ this would not work properly if we return the reference found.
+ (For example, with "struct foo" in an outer scope, "union foo;"
+ must shadow that tag with a new one of union type.) */
+ if (ref && TREE_CODE (ref) == code)
return ref;
- 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,
@@ -5698,13 +5594,11 @@ xref_tag (code, name)
ref = make_node (code);
if (code == ENUMERAL_TYPE)
{
- /* (In ANSI, Enums can be referred to only if already defined.) */
- if (pedantic)
- pedwarn ("ANSI C forbids forward references to `enum' types");
/* Give the type a default layout like unsigned int
to avoid crashing if it does not get defined. */
TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
+ 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);
@@ -5713,17 +5607,12 @@ xref_tag (code, name)
pushtag (name, ref);
- pop_obstacks ();
-
return ref;
}
/* Make sure that the tag NAME is defined *in the current binding level*
at least as a forward reference.
- CODE says which kind of tag NAME ought to be.
-
- We also do a push_obstacks_nochange
- whose matching pop is in finish_struct. */
+ CODE says which kind of tag NAME ought to be. */
tree
start_struct (code, name)
@@ -5733,11 +5622,7 @@ start_struct (code, name)
/* If there is already a tag defined at this binding level
(as a forward reference), just return it. */
- register tree ref = 0;
-
- push_obstacks_nochange ();
- if (current_binding_level == global_binding_level)
- end_temporary_allocation ();
+ tree ref = 0;
if (name != 0)
ref = lookup_tag (code, name, current_binding_level, 1);
@@ -5746,9 +5631,14 @@ start_struct (code, name)
C_TYPE_BEING_DEFINED (ref) = 1;
TYPE_PACKED (ref) = flag_pack_struct;
if (TYPE_FIELDS (ref))
- error ((code == UNION_TYPE ? "redefinition of `union %s'"
- : "redefinition of `struct %s'"),
- IDENTIFIER_POINTER (name));
+ {
+ if (code == UNION_TYPE)
+ error ("redefinition of `union %s'",
+ IDENTIFIER_POINTER (name));
+ else
+ error ("redefinition of `struct %s'",
+ IDENTIFIER_POINTER (name));
+ }
return ref;
}
@@ -5764,7 +5654,7 @@ start_struct (code, name)
/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
of a structure component, returning a FIELD_DECL node.
- WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node.
+ WIDTH is non-NULL for bit-fields only, and is an INTEGER_CST node.
This is done during the parsing of the struct declaration.
The FIELD_DECL nodes are chained together and the lot of them
@@ -5778,43 +5668,29 @@ grokfield (filename, line, declarator, declspecs, width)
{
tree value;
- /* The corresponding pop_obstacks is in finish_decl. */
- push_obstacks_nochange ();
+ if (declarator == NULL_TREE && width == NULL_TREE)
+ {
+ /* This is an unnamed decl. We only support unnamed
+ structs/unions, so check for other things and refuse them. */
+ 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);
+ value = grokdeclarator (declarator, declspecs, FIELD, 0, width);
finish_decl (value, NULL_TREE, NULL_TREE);
- DECL_INITIAL (value) = width;
maybe_objc_check_decl (value);
return value;
}
-/* Function to help qsort sort FIELD_DECLs by name order. */
-
-static int
-field_decl_cmp (xp, yp)
- const GENERIC_PTR xp;
- const GENERIC_PTR yp;
-{
- tree *x = (tree *)xp, *y = (tree *)yp;
-
- if (DECL_NAME (*x) == DECL_NAME (*y))
- return 0;
- if (DECL_NAME (*x) == NULL)
- return -1;
- if (DECL_NAME (*y) == NULL)
- return 1;
- if (DECL_NAME (*x) < DECL_NAME (*y))
- return -1;
- return 1;
-}
-
/* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
FIELDLIST is a chain of FIELD_DECL nodes for the fields.
- ATTRIBUTES are attributes to be applied to the structure.
-
- We also do a pop_obstacks to match the push in start_struct. */
+ ATTRIBUTES are attributes to be applied to the structure. */
tree
finish_struct (t, fieldlist, attributes)
@@ -5822,16 +5698,16 @@ finish_struct (t, fieldlist, attributes)
tree fieldlist;
tree attributes;
{
- register tree x;
- int old_momentary;
+ tree x;
int toplevel = global_binding_level == current_binding_level;
+ int saw_named_field;
/* If this type was previously laid out as a forward reference,
make sure we lay it out again. */
TYPE_SIZE (t) = 0;
- decl_attributes (t, attributes, NULL_TREE);
+ decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
/* Nameless union parm types are useful as GCC extension. */
if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic)
@@ -5839,15 +5715,13 @@ finish_struct (t, fieldlist, attributes)
if (in_parm_level_p ())
{
if (pedantic)
- pedwarn ((TREE_CODE (t) == UNION_TYPE ? "union defined inside parms"
- : "structure defined inside parms"));
+ pedwarn ("%s defined inside parms",
+ TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
else if (! flag_traditional)
- warning ((TREE_CODE (t) == UNION_TYPE ? "union defined inside parms"
- : "structure defined inside parms"));
+ warning ("%s defined inside parms",
+ TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
}
- old_momentary = suspend_momentary ();
-
if (pedantic)
{
for (x = fieldlist; x; x = TREE_CHAIN (x))
@@ -5855,24 +5729,18 @@ finish_struct (t, fieldlist, attributes)
break;
if (x == 0)
- pedwarn ((fieldlist
- ? "%s has no named members"
- : "%s has no members"),
- TREE_CODE (t) == UNION_TYPE ? "union" : "struct");
+ 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.
- Store 0 there, except for ": 0" fields (so we can find them
- and delete them, below). */
+ /* Install struct as DECL_CONTEXT of each field decl. */
+ saw_named_field = 0;
for (x = fieldlist; x; x = TREE_CHAIN (x))
{
DECL_CONTEXT (x) = t;
DECL_PACKED (x) |= TYPE_PACKED (t);
- DECL_FIELD_SIZE (x) = 0;
/* If any field is const, the structure type is pseudo-const. */
if (TREE_READONLY (x))
@@ -5902,100 +5770,34 @@ finish_struct (t, fieldlist, attributes)
error ("nested redefinition of `%s'",
IDENTIFIER_POINTER (TYPE_NAME (t)));
- /* Detect invalid bit-field size. */
- if (DECL_INITIAL (x))
- STRIP_NOPS (DECL_INITIAL (x));
- if (DECL_INITIAL (x))
- {
- if (TREE_CODE (DECL_INITIAL (x)) == INTEGER_CST)
- constant_expression_warning (DECL_INITIAL (x));
- else
- {
- error_with_decl (x, "bit-field `%s' width not an integer constant");
- DECL_INITIAL (x) = NULL;
- }
- }
-
- /* Detect invalid bit-field type. */
- if (DECL_INITIAL (x)
- && TREE_CODE (TREE_TYPE (x)) != INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE)
- {
- error_with_decl (x, "bit-field `%s' has invalid type");
- DECL_INITIAL (x) = NULL;
- }
- if (DECL_INITIAL (x) && pedantic
- && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != integer_type_node
- && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != unsigned_type_node
- /* Accept an enum that's equivalent to int or unsigned int. */
- && !(TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
- && (TYPE_PRECISION (TREE_TYPE (x))
- == TYPE_PRECISION (integer_type_node))))
- pedwarn_with_decl (x, "bit-field `%s' type invalid in ANSI C");
-
- /* Detect and ignore out of range field width. */
- if (DECL_INITIAL (x))
- {
- unsigned HOST_WIDE_INT width = TREE_INT_CST_LOW (DECL_INITIAL (x));
-
- if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
- {
- DECL_INITIAL (x) = NULL;
- error_with_decl (x, "negative width in bit-field `%s'");
- }
- else if (TREE_INT_CST_HIGH (DECL_INITIAL (x)) != 0
- || width > TYPE_PRECISION (TREE_TYPE (x)))
- {
- DECL_INITIAL (x) = NULL;
- pedwarn_with_decl (x, "width of `%s' exceeds its type");
- }
- else if (width == 0 && DECL_NAME (x) != 0)
- {
- error_with_decl (x, "zero width for bit-field `%s'");
- DECL_INITIAL (x) = NULL;
- }
- }
-
- /* Process valid field width. */
- if (DECL_INITIAL (x))
- {
- register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
-
- if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
- && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
- TREE_UNSIGNED (TREE_TYPE (x)))
- || width < min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
- TREE_UNSIGNED (TREE_TYPE (x)))))
- warning_with_decl (x, "`%s' is narrower than values of its type");
-
- DECL_FIELD_SIZE (x) = width;
- DECL_BIT_FIELD (x) = DECL_C_BIT_FIELD (x) = 1;
- DECL_INITIAL (x) = NULL;
-
- if (width == 0)
- {
- /* field size 0 => force desired amount of alignment. */
-#ifdef EMPTY_FIELD_BOUNDARY
- DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
-#endif
-#ifdef PCC_BITFIELD_TYPE_MATTERS
- if (PCC_BITFIELD_TYPE_MATTERS)
- DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
- TYPE_ALIGN (TREE_TYPE (x)));
-#endif
- }
- }
- else if (TREE_TYPE (x) != error_mark_node)
+ if (TREE_TYPE (x) != error_mark_node && !DECL_BIT_FIELD (x))
{
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. */
+ /* Detect flexible array member in an invalid context. */
+ 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;
+ }
/* Delete all duplicate fields from the fieldlist */
for (x = fieldlist; x && TREE_CHAIN (x);)
@@ -6004,8 +5806,8 @@ finish_struct (t, fieldlist, attributes)
x = TREE_CHAIN (x);
else
{
- register tree y = fieldlist;
-
+ tree y = fieldlist;
+
while (1)
{
if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x)))
@@ -6019,7 +5821,8 @@ finish_struct (t, fieldlist, attributes)
error_with_decl (TREE_CHAIN (x), "duplicate member `%s'");
TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
}
- else x = TREE_CHAIN (x);
+ else
+ x = TREE_CHAIN (x);
}
/* Now we have the nearly final fieldlist. Record it,
@@ -6029,65 +5832,27 @@ finish_struct (t, fieldlist, attributes)
layout_type (t);
- /* Delete all zero-width bit-fields from the front of the fieldlist */
- while (fieldlist
- && DECL_INITIAL (fieldlist))
- fieldlist = TREE_CHAIN (fieldlist);
- /* Delete all such members from the rest of the fieldlist */
- for (x = fieldlist; x;)
- {
- if (TREE_CHAIN (x) && DECL_INITIAL (TREE_CHAIN (x)))
- TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
- else x = TREE_CHAIN (x);
- }
-
- /* Now we have the truly final field list.
- Store it in this type and in the variants. */
-
- TYPE_FIELDS (t) = fieldlist;
-
- /* If there are lots of fields, sort so we can look through them fast.
- We arbitrarily consider 16 or more elts to be "a lot". */
+ /* Delete all zero-width bit-fields from the fieldlist */
{
- int len = 0;
-
- for (x = fieldlist; x; x = TREE_CHAIN (x))
- {
- if (len > 15)
- break;
- len += 1;
- }
- if (len > 15)
- {
- tree *field_array;
- char *space;
-
- len += list_length (x);
- /* Use the same allocation policy here that make_node uses, to
- ensure that this lives as long as the rest of the struct decl.
- All decls in an inline function need to be saved. */
- if (allocation_temporary_p ())
- space = savealloc (sizeof (struct lang_type) + len * sizeof (tree));
- else
- space = oballoc (sizeof (struct lang_type) + len * sizeof (tree));
-
- TYPE_LANG_SPECIFIC (t) = (struct lang_type *) space;
- TYPE_LANG_SPECIFIC (t)->len = len;
+ tree *fieldlistp = &fieldlist;
+ while (*fieldlistp)
+ if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp))
+ *fieldlistp = TREE_CHAIN (*fieldlistp);
+ else
+ fieldlistp = &TREE_CHAIN (*fieldlistp);
+ }
- field_array = &TYPE_LANG_SPECIFIC (t)->elts[0];
- len = 0;
- for (x = fieldlist; x; x = TREE_CHAIN (x))
- field_array[len++] = x;
+ /* Now we have the truly final field list.
+ Store it in this type and in the variants. */
- qsort (field_array, len, sizeof (tree), field_decl_cmp);
- }
- }
+ 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 this was supposed to be a transparent union, but we can't
@@ -6108,37 +5873,45 @@ finish_struct (t, fieldlist, attributes)
tree decl;
for (decl = current_binding_level->names; decl; decl = TREE_CHAIN (decl))
{
- if (TREE_TYPE (decl) == t
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TYPE_MAIN_VARIANT (t)
&& TREE_CODE (decl) != TYPE_DECL)
{
layout_decl (decl, 0);
/* This is a no-op in c-lang.c or something real in objc-actions.c. */
maybe_objc_check_decl (decl);
- rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
+ rest_of_decl_compilation (decl, NULL, toplevel, 0);
if (! toplevel)
expand_decl (decl);
- --current_binding_level->n_incomplete;
+ if (--current_binding_level->n_incomplete == 0)
+ break;
}
- 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);
while (TREE_CODE (element) == ARRAY_TYPE)
element = TREE_TYPE (element);
if (element == t)
- layout_array_type (TREE_TYPE (decl));
+ {
+ layout_array_type (TREE_TYPE (decl));
+ if (TREE_CODE (decl) != TYPE_DECL)
+ {
+ layout_decl (decl, 0);
+ maybe_objc_check_decl (decl);
+ rest_of_decl_compilation (decl, NULL, toplevel, 0);
+ if (! toplevel)
+ expand_decl (decl);
+ }
+ if (--current_binding_level->n_incomplete == 0)
+ break;
+ }
}
}
}
- 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;
}
@@ -6163,7 +5936,7 @@ tree
start_enum (name)
tree name;
{
- register tree enumtype = 0;
+ tree enumtype = 0;
/* If this is the real definition for a previous forward reference,
fill in the contents in the same object that used to be the
@@ -6172,12 +5945,6 @@ start_enum (name)
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);
@@ -6217,82 +5984,101 @@ finish_enum (enumtype, values, attributes)
tree values;
tree attributes;
{
- register tree pair, tem;
- tree minnode = 0, maxnode = 0;
- int lowprec, highprec, precision;
- int toplevel = global_binding_level == current_binding_level;
+ 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, NULL_TREE);
+ decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
/* Calculate the maximum value of any enumerator in this type. */
if (values == error_mark_node)
minnode = maxnode = integer_zero_node;
else
- for (pair = values; pair; pair = TREE_CHAIN (pair))
- {
- tree value = TREE_VALUE (pair);
- if (pair == values)
- minnode = maxnode = TREE_VALUE (pair);
- else
- {
- if (tree_int_cst_lt (maxnode, value))
- maxnode = value;
- if (tree_int_cst_lt (value, minnode))
- minnode = value;
- }
- }
-
- TYPE_MIN_VALUE (enumtype) = minnode;
- TYPE_MAX_VALUE (enumtype) = maxnode;
-
- /* An enum can have some negative values; then it is signed. */
- TREE_UNSIGNED (enumtype) = tree_int_cst_sgn (minnode) >= 0;
-
- /* Determine the precision this type needs. */
-
- lowprec = min_precision (minnode, TREE_UNSIGNED (enumtype));
- highprec = min_precision (maxnode, TREE_UNSIGNED (enumtype));
- precision = MAX (lowprec, highprec);
+ {
+ 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;
+ }
+ }
+ /* Construct the final type of this enumeration. It is the same
+ as one of the integral types - the narrowest one that fits, except
+ that normally we only go as narrow as int - and signed iff any of
+ the values are negative. */
+ 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, 1);
+ tree narrowest = type_for_size (precision, unsign);
if (narrowest == 0)
{
warning ("enumeration values exceed range of largest integer");
narrowest = long_long_integer_type_node;
}
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (narrowest);
+ precision = TYPE_PRECISION (narrowest);
}
else
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
+ 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)
{
- /* Change the type of the enumerators to be the enum type.
- Formerly this was done only for enums that fit in an int,
- but the comment said it was done only for enums wider than int.
- It seems necessary to do this for wide enums,
- and best not to change what's done for ordinary narrower ones. */
+ /* Change the type of the enumerators to be the enum type. We
+ need to do this irrespective of the size of the enum, for
+ proper type checking. Replace the DECL_INITIALs of the
+ enumerators, and the value slots of the list, with copies
+ that have the enum type; they cannot be modified in place
+ because they may be shared (e.g. integer_zero_node) Finally,
+ change the purpose slots to point to the names of the decls. */
for (pair = values; pair; pair = TREE_CHAIN (pair))
{
- TREE_TYPE (TREE_PURPOSE (pair)) = enumtype;
- DECL_SIZE (TREE_PURPOSE (pair)) = TYPE_SIZE (enumtype);
- if (TREE_CODE (TREE_PURPOSE (pair)) != FUNCTION_DECL)
- DECL_ALIGN (TREE_PURPOSE (pair)) = TYPE_ALIGN (enumtype);
- }
+ 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);
+
+ /* 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));
- /* Replace the decl nodes in VALUES with their names. */
- for (pair = values; pair; pair = TREE_CHAIN (pair))
- TREE_PURPOSE (pair) = DECL_NAME (TREE_PURPOSE (pair));
+ TREE_PURPOSE (pair) = DECL_NAME (enu);
+ TREE_VALUE (pair) = DECL_INITIAL (enu);
+ }
TYPE_VALUES (enumtype) = values;
}
@@ -6300,6 +6086,8 @@ finish_enum (enumtype, values, attributes)
/* Fix up all variant types of this enum type. */
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);
@@ -6308,15 +6096,13 @@ finish_enum (enumtype, values, attributes)
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;
}
@@ -6329,7 +6115,7 @@ tree
build_enumerator (name, value)
tree name, value;
{
- register tree decl, type;
+ tree decl, type;
/* Validate and default VALUE. */
@@ -6364,8 +6150,8 @@ build_enumerator (name, value)
if (pedantic && ! int_fits_type_p (value, integer_type_node))
{
- pedwarn ("ANSI C restricts enumerator values to range of `int'");
- value = integer_zero_node;
+ pedwarn ("ISO C restricts enumerator values to range of `int'");
+ value = convert (integer_type_node, value);
}
/* Set basis for default for next value. */
@@ -6382,15 +6168,15 @@ build_enumerator (name, 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);
}
+
/* Create the FUNCTION_DECL for a function definition.
- DECLSPECS, DECLARATOR, PREFIX_ATTRIBUTES and ATTRIBUTES are the parts of
+ DECLSPECS, DECLARATOR and ATTRIBUTES are the parts of
the declaration; they describe the function's name and the type it returns,
but twisted together in a fashion that parallels the syntax of C.
@@ -6399,14 +6185,11 @@ build_enumerator (name, value)
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)
- tree declarator, declspecs, prefix_attributes, attributes;
- int nested;
+start_function (declspecs, declarator, attributes)
+ tree declarator, declspecs, attributes;
{
tree decl1, old_decl;
tree restype;
@@ -6423,7 +6206,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
/* Don't expand any sizes in the return type of the function. */
immediate_size_expand = 0;
- decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1);
+ decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL_TREE);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
@@ -6433,13 +6216,19 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
return 0;
}
- decl_attributes (decl1, prefix_attributes, attributes);
+ decl_attributes (&decl1, attributes, 0);
+
+ 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 (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,
@@ -6447,7 +6236,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
}
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. */
@@ -6481,13 +6270,19 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
/* Optionally warn of old-fashioned def with no previous prototype. */
if (warn_strict_prototypes
&& TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0
- && !(old_decl != 0 && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0))
+ && !(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");
/* Optionally warn of any global def with no previous prototype. */
else if (warn_missing_prototypes
&& TREE_PUBLIC (decl1)
- && !(old_decl != 0 && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0)
- && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))))
+ && !(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'");
/* Optionally warn of any def with no previous prototype
if the function has already been used. */
@@ -6495,12 +6290,12 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
&& 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");
+ "`%s' was used with no prototype before its definition");
/* Optionally warn of any global def with no previous declaration. */
else if (warn_missing_declarations
&& TREE_PUBLIC (decl1)
&& old_decl == 0
- && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))))
+ && ! MAIN_NAME_P (DECL_NAME (decl1)))
warning_with_decl (decl1, "no previous declaration for `%s'");
/* Optionally warn of any def with no previous declaration
if the function has already been used. */
@@ -6508,7 +6303,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
&& 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");
+ "`%s' was used with no declaration before its definition");
/* This is a definition, not a reference.
So normally clear DECL_EXTERNAL.
@@ -6516,10 +6311,6 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
except for defining how to inline. So set DECL_EXTERNAL in that case. */
DECL_EXTERNAL (decl1) = current_extern_inline;
-#ifdef SET_DEFAULT_DECL_ATTRIBUTES
- SET_DEFAULT_DECL_ATTRIBUTES (decl1, attributes);
-#endif
-
/* This function exists in static storage.
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
@@ -6528,15 +6319,14 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
if (current_function_decl != 0)
TREE_PUBLIC (decl1) = 0;
- /* Warn for unlikely, improbable, or stupid declarations of `main'. */
- if (warn_main > 0
- && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))) == 0)
+ /* Warn for unlikely, improbable, or stupid declarations of `main'. */
+ 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)
+ != integer_type_node)
pedwarn_with_decl (decl1, "return type of `%s' is not `int'");
for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args;
@@ -6562,7 +6352,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
!= char_type_node))
pedwarn_with_decl (decl1,
- "second argument of `%s' should be `char **'");
+ "second argument of `%s' should be `char **'");
break;
case 3:
@@ -6571,20 +6361,17 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
!= char_type_node))
pedwarn_with_decl (decl1,
- "third argument of `%s' should probably be `char **'");
+ "third argument of `%s' should probably be `char **'");
break;
}
}
/* It is intentional that this message does not mention the third
- argument, which is warned for only pedantically, because it's
- blessed by mention in an appendix of the standard. */
+ argument because it's only mentioned in an appendix of the
+ standard. */
if (argct > 0 && (argct < 2 || argct > 3))
pedwarn_with_decl (decl1, "`%s' takes only zero or two arguments");
- if (argct == 3 && pedantic)
- pedwarn_with_decl (decl1, "third argument of `%s' is deprecated");
-
if (! TREE_PUBLIC (decl1))
pedwarn_with_decl (decl1, "`%s' is normally a non-static function");
}
@@ -6599,11 +6386,11 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
declare_parm_level (1);
current_binding_level->subblocks_tag_transparent = 1;
- make_function_rtl (current_function_decl);
+ make_decl_rtl (current_function_decl, NULL);
restype = TREE_TYPE (TREE_TYPE (current_function_decl));
/* Promote the value to int before returning it. */
- if (C_PROMOTING_INTEGER_TYPE_P (restype))
+ if (c_promoting_integer_type_p (restype))
{
/* It retains unsignedness if traditional
or if not really getting wider. */
@@ -6618,11 +6405,6 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
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)))
@@ -6630,6 +6412,8 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
immediate_size_expand = old_immediate_size_expand;
+ start_fname_decls ();
+
return 1;
}
@@ -6653,8 +6437,8 @@ c_mark_varargs ()
void
store_parm_decls ()
{
- register tree fndecl = current_function_decl;
- register tree parm;
+ tree fndecl = current_function_decl;
+ tree parm;
/* This is either a chain of PARM_DECLs (if a prototype was used)
or a list of IDENTIFIER_NODEs (for an old-fashioned C definition). */
@@ -6664,16 +6448,24 @@ store_parm_decls ()
tree parmtags = current_function_parm_tags;
/* This is a chain of PARM_DECLs from old-style parm declarations. */
- register tree parmdecls = getdecls ();
+ tree parmdecls = getdecls ();
/* This is a chain of any other decls that came in among the parm
declarations. If a parm is declared with enum {foo, bar} x;
then CONST_DECLs for foo and bar are put here. */
tree nonparms = 0;
+ /* The function containing FNDECL, if any. */
+ tree context = decl_function_context (fndecl);
+
/* Nonzero if this definition is written with a prototype. */
int prototype = 0;
+ int saved_warn_shadow = warn_shadow;
+
+ /* Don't re-emit shadow warnings. */
+ warn_shadow = 0;
+
if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST)
{
/* This case is when the function was defined with an ANSI prototype.
@@ -6681,7 +6473,7 @@ store_parm_decls ()
except record them as in effect
and complain if any redundant old-style parm decls were written. */
- register tree next;
+ tree next;
tree others = 0;
prototype = 1;
@@ -6713,7 +6505,8 @@ store_parm_decls ()
{
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
@@ -6747,8 +6540,7 @@ store_parm_decls ()
won't depend on its type. */
TREE_TYPE (dummy) = integer_type_node;
DECL_ARG_TYPE (dummy) = integer_type_node;
- DECL_ARGUMENTS (fndecl)
- = chainon (DECL_ARGUMENTS (fndecl), dummy);
+ DECL_ARGUMENTS (fndecl) = chainon (DECL_ARGUMENTS (fndecl), dummy);
}
#endif
@@ -6780,16 +6572,19 @@ store_parm_decls ()
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))
{
- register tree tail, found = NULL;
+ tree tail, found = NULL;
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;
}
@@ -6805,15 +6600,15 @@ store_parm_decls ()
}
/* If declaration already marked, we have a duplicate name.
- Complain, and don't use this decl twice. */
- if (found && DECL_RESULT (found) != 0)
+ Complain, and don't use this decl twice. */
+ if (found && DECL_WEAK (found))
{
error_with_decl (found, "multiple parameters named `%s'");
found = 0;
}
/* If the declaration says "void", complain and ignore it. */
- if (found && 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;
@@ -6838,17 +6633,17 @@ store_parm_decls ()
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
@@ -6858,7 +6653,7 @@ store_parm_decls ()
any actual PARM_DECLs not matched with any names. */
nonparms = 0;
- for (parm = parmdecls; parm; )
+ for (parm = parmdecls; parm;)
{
tree next = TREE_CHAIN (parm);
TREE_CHAIN (parm) = 0;
@@ -6868,20 +6663,20 @@ store_parm_decls ()
else
{
/* Complain about args with incomplete types. */
- if (TYPE_SIZE (TREE_TYPE (parm)) == 0)
- {
- error_with_decl (parm, "parameter `%s' has incomplete type");
- TREE_TYPE (parm) = error_mark_node;
- }
-
- if (DECL_RESULT (parm) == 0)
- {
- error_with_decl (parm,
- "declaration for parameter `%s' but no such parameter");
+ if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
+ {
+ error_with_decl (parm, "parameter `%s' has incomplete type");
+ TREE_TYPE (parm) = error_mark_node;
+ }
+
+ if (! DECL_WEAK (parm))
+ {
+ error_with_decl (parm,
+ "declaration for parameter `%s' but no such parameter");
/* Pretend the parameter was not missing.
This gets us to a standard state and minimizes
further error messages. */
- specparms
+ specparms
= chainon (specparms,
tree_cons (parm, NULL_TREE, NULL_TREE));
}
@@ -6890,12 +6685,13 @@ store_parm_decls ()
parm = next;
}
- /* Chain the declarations together in the order of the list of names. */
- /* Store that chain in the function decl, replacing the list of names. */
+ /* Chain the declarations together in the order of the list of
+ names. Store that chain in the function decl, replacing the
+ list of names. */
parm = specparms;
DECL_ARGUMENTS (fndecl) = 0;
{
- register tree last;
+ tree last;
for (last = 0; parm; parm = TREE_CHAIN (parm))
if (TREE_PURPOSE (parm))
{
@@ -6914,7 +6710,7 @@ store_parm_decls ()
if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
{
- register tree type;
+ tree type;
for (parm = DECL_ARGUMENTS (fndecl),
type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type))
@@ -6930,9 +6726,11 @@ store_parm_decls ()
"prototype declaration");
break;
}
- /* Type for passing arg must be consistent
- with that declared for the arg. */
- if (! comptypes (DECL_ARG_TYPE (parm), TREE_VALUE (type)))
+ /* Type for passing arg must be consistent with that
+ declared for the arg. ISO C says we take the unqualified
+ type for parameters declared with qualified type. */
+ if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
+ TYPE_MAIN_VARIANT (TREE_VALUE (type))))
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
== TYPE_MAIN_VARIANT (TREE_VALUE (type)))
@@ -6943,13 +6741,13 @@ store_parm_decls ()
`int foo(float x) {...}'. This is particularly
useful for argument types like uid_t. */
DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
-#ifdef PROMOTE_PROTOTYPES
- if ((TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
- || TREE_CODE (TREE_TYPE (parm)) == ENUMERAL_TYPE)
+
+ 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;
-#endif
+
if (pedantic)
{
pedwarn ("promoted argument `%s' doesn't match prototype",
@@ -6985,15 +6783,14 @@ store_parm_decls ()
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
@@ -7038,175 +6835,37 @@ store_parm_decls ()
gen_aux_info_record (fndecl, 1, 0, prototype);
/* Initialize the RTL code for the function. */
-
init_function_start (fndecl, input_filename, lineno);
- /* If this is a varargs function, inform function.c. */
-
- if (c_function_varargs)
- mark_varargs ();
-
- /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
-
- declare_function_name ();
-
- /* Set up parameters and prepare for return, for the function. */
-
- expand_function_start (fndecl, 0);
-
- /* If this function is `main', emit a call to `__main'
- to run global initializers, etc. */
- if (DECL_NAME (fndecl)
- && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main") == 0
- && DECL_CONTEXT (fndecl) == NULL_TREE)
- expand_main_function ();
-}
-
-/* SPECPARMS is an identifier list--a chain of TREE_LIST nodes
- each with a parm name as the TREE_VALUE. A null pointer as TREE_VALUE
- stands for an ellipsis in the identifier list.
-
- PARMLIST is the data returned by get_parm_info for the
- parmlist that follows the semicolon.
-
- We return a value of the same sort that get_parm_info returns,
- except that it describes the combination of identifiers and parmlist. */
-
-tree
-combine_parm_decls (specparms, parmlist, void_at_end)
- tree specparms, parmlist;
- int void_at_end;
-{
- register tree fndecl = current_function_decl;
- register tree parm;
-
- tree parmdecls = TREE_PURPOSE (parmlist);
-
- /* This is a chain of any other decls that came in among the parm
- declarations. They were separated already by get_parm_info,
- so we just need to keep them separate. */
- tree nonparms = TREE_VALUE (parmlist);
-
- tree types = 0;
-
- for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
- DECL_RESULT (parm) = 0;
+ /* Begin the statement tree for this function. */
+ begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
- for (parm = specparms; parm; parm = TREE_CHAIN (parm))
+ /* If this is a nested function, save away the sizes of any
+ variable-size types so that we can expand them when generating
+ RTL. */
+ if (context)
{
- register tree tail, found = NULL;
-
- /* See if any of the parmdecls specifies this parm by name. */
- for (tail = parmdecls; tail; tail = TREE_CHAIN (tail))
- if (DECL_NAME (tail) == TREE_VALUE (parm))
- {
- found = tail;
- break;
- }
-
- /* If declaration already marked, we have a duplicate name.
- Complain, and don't use this decl twice. */
- if (found && DECL_RESULT (found) != 0)
- {
- error_with_decl (found, "multiple parameters named `%s'");
- found = 0;
- }
-
- /* If the declaration says "void", complain and ignore it. */
- if (found && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == void_type_node)
- {
- error_with_decl (found, "parameter `%s' declared void");
- TREE_TYPE (found) = integer_type_node;
- DECL_ARG_TYPE (found) = integer_type_node;
- layout_decl (found, 0);
- }
-
- /* Traditionally, a parm declared float is actually a double. */
- if (found && flag_traditional
- && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == float_type_node)
- {
- TREE_TYPE (found) = double_type_node;
- DECL_ARG_TYPE (found) = double_type_node;
- layout_decl (found, 0);
- }
-
- /* If no declaration found, default to int. */
- if (!found)
- {
- found = build_decl (PARM_DECL, TREE_VALUE (parm),
- integer_type_node);
- DECL_ARG_TYPE (found) = TREE_TYPE (found);
- DECL_SOURCE_LINE (found) = DECL_SOURCE_LINE (fndecl);
- DECL_SOURCE_FILE (found) = DECL_SOURCE_FILE (fndecl);
- error_with_decl (found, "type of parameter `%s' is not declared");
- pushdecl (found);
- }
-
- TREE_PURPOSE (parm) = found;
-
- /* Mark this decl as "already found" -- see test, above.
- It is safe to use DECL_RESULT for this
- since it is not used in PARM_DECLs or CONST_DECLs. */
- DECL_RESULT (found) = error_mark_node;
+ 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;
}
- /* Complain about any actual PARM_DECLs not matched with any names. */
-
- for (parm = parmdecls; parm; )
- {
- tree next = TREE_CHAIN (parm);
- TREE_CHAIN (parm) = 0;
-
- /* Complain about args with incomplete types. */
- if (TYPE_SIZE (TREE_TYPE (parm)) == 0)
- {
- error_with_decl (parm, "parameter `%s' has incomplete type");
- TREE_TYPE (parm) = error_mark_node;
- }
+ /* This function is being processed in whole-function mode. */
+ cfun->x_whole_function_mode_p = 1;
- if (DECL_RESULT (parm) == 0)
- {
- error_with_decl (parm,
- "declaration for parameter `%s' but no such parameter");
- /* Pretend the parameter was not missing.
- This gets us to a standard state and minimizes
- further error messages. */
- specparms
- = chainon (specparms,
- tree_cons (parm, NULL_TREE, NULL_TREE));
- }
-
- parm = next;
- }
-
- /* Chain the declarations together in the order of the list of names.
- At the same time, build up a list of their types, in reverse order. */
-
- parm = specparms;
- parmdecls = 0;
- {
- register tree last;
- for (last = 0; parm; parm = TREE_CHAIN (parm))
- if (TREE_PURPOSE (parm))
- {
- if (last == 0)
- parmdecls = TREE_PURPOSE (parm);
- else
- TREE_CHAIN (last) = TREE_PURPOSE (parm);
- last = TREE_PURPOSE (parm);
- TREE_CHAIN (last) = 0;
-
- types = saveable_tree_cons (NULL_TREE, TREE_TYPE (parm), types);
- }
- }
-
- if (void_at_end)
- return saveable_tree_cons (parmdecls, nonparms,
- nreverse (saveable_tree_cons (NULL_TREE,
- void_type_node,
- types)));
+ /* Even though we're inside a function body, we still don't want to
+ call expand_expr to calculate the size of a variable-sized array.
+ We haven't necessarily assigned RTL to all variables yet, so it's
+ not safe to try to expand expressions involving them. */
+ immediate_size_expand = 0;
+ cfun->x_dont_save_pending_sizes_p = 1;
- return saveable_tree_cons (parmdecls, nonparms, nreverse (types));
+ warn_shadow = saved_warn_shadow;
}
/* Finish up a function declaration and compile that function
@@ -7221,7 +6880,7 @@ void
finish_function (nested)
int nested;
{
- register tree fndecl = current_function_decl;
+ tree fndecl = current_function_decl;
/* TREE_READONLY (fndecl) = 1;
This caused &foo to be of type ptr-to-const-function
@@ -7241,13 +6900,13 @@ finish_function (nested)
setjmp_protect_args ();
}
- if (! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main"))
+ if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted)
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
!= integer_type_node)
{
/* If warn_main is 1 (-Wmain) or 2 (-Wall), we have already warned.
- If warn_main is -1 (-Wno-main) we don't want to be warned. */
+ If warn_main is -1 (-Wno-main) we don't want to be warned. */
if (! warn_main)
pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
}
@@ -7256,38 +6915,170 @@ finish_function (nested)
#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
}
}
+
+ finish_fname_decls ();
+
+ /* Tie off the statement tree for this function. */
+ finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+ /* Clear out memory we no longer need. */
+ free_after_parsing (cfun);
+ /* Since we never call rest_of_compilation, we never clear
+ CFUN. Do so explicitly. */
+ free_after_compilation (cfun);
+ cfun = NULL;
+
+ if (! nested)
+ {
+ /* Generate RTL for the body of this function. */
+ c_expand_body (fndecl, nested, 1);
+ /* Let the error reporting routines know that we're outside a
+ function. For a nested function, this value is used in
+ pop_c_function_context and then reset via pop_function_context. */
+ current_function_decl = NULL;
+ }
+}
+
+/* Generate the RTL for a deferred function FNDECL. */
+
+void
+c_expand_deferred_function (fndecl)
+ tree fndecl;
+{
+ /* DECL_INLINE or DECL_RESULT might got cleared after the inline
+ function was deferred, e.g. in duplicate_decls. */
+ if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl))
+ {
+ c_expand_body (fndecl, 0, 0);
+ current_function_decl = NULL;
+ }
+}
+
+/* Generate the RTL for the body of FNDECL. If NESTED_P is non-zero,
+ then we are already in the process of generating RTL for another
+ function. If can_defer_p is zero, we won't attempt to defer the
+ generation of RTL. */
+
+static void
+c_expand_body (fndecl, nested_p, can_defer_p)
+ tree fndecl;
+ int nested_p, can_defer_p;
+{
+ int uninlinable = 1;
+
+ /* There's no reason to do any of the work here if we're only doing
+ semantic analysis; this code just generates RTL. */
+ if (flag_syntax_only)
+ return;
+
+ if (flag_inline_trees)
+ {
+ /* First, cache whether the current function is inlinable. Some
+ predicates depend on cfun and current_function_decl to
+ function completely. */
+ timevar_push (TV_INTEGRATION);
+ uninlinable = ! tree_inlinable_function_p (fndecl);
+
+ if (! uninlinable && can_defer_p
+ /* Save function tree for inlining. Should return 0 if the
+ language does not support function deferring or the
+ function could not be deferred. */
+ && defer_fn (fndecl))
+ {
+ /* Let the back-end know that this function exists. */
+ (*debug_hooks->deferred_inline_function) (fndecl);
+ timevar_pop (TV_INTEGRATION);
+ return;
+ }
+
+ /* Then, inline any functions called in it. */
+ optimize_inline_calls (fndecl);
+ timevar_pop (TV_INTEGRATION);
+ }
+
+ timevar_push (TV_EXPAND);
+
+ if (nested_p)
+ {
+ /* Make sure that we will evaluate variable-sized types involved
+ in our function's type. */
+ expand_pending_sizes (DECL_LANG_SPECIFIC (fndecl)->pending_sizes);
+ /* Squirrel away our current state. */
+ push_function_context ();
+ }
+
+ /* Initialize the RTL code for the function. */
+ current_function_decl = fndecl;
+ input_filename = DECL_SOURCE_FILE (fndecl);
+ init_function_start (fndecl, input_filename, DECL_SOURCE_LINE (fndecl));
+
+ /* This function is being processed in whole-function mode. */
+ cfun->x_whole_function_mode_p = 1;
+
+ /* Even though we're inside a function body, we still don't want to
+ call expand_expr to calculate the size of a variable-sized array.
+ We haven't necessarily assigned RTL to all variables yet, so it's
+ not safe to try to expand expressions involving them. */
+ immediate_size_expand = 0;
+ cfun->x_dont_save_pending_sizes_p = 1;
+
+ /* If this is a varargs function, inform function.c. */
+ if (c_function_varargs)
+ mark_varargs ();
+
+ /* Set up parameters and prepare for return, for the function. */
+ expand_function_start (fndecl, 0);
+
+ /* If this function is `main', emit a call to `__main'
+ to run global initializers, etc. */
+ if (DECL_NAME (fndecl)
+ && MAIN_NAME_P (DECL_NAME (fndecl))
+ && DECL_CONTEXT (fndecl) == NULL_TREE)
+ expand_main_function ();
+
+ /* Generate the RTL for this function. */
+ expand_stmt (DECL_SAVED_TREE (fndecl));
+ if (uninlinable)
+ {
+ /* Allow the body of the function to be garbage collected. */
+ DECL_SAVED_TREE (fndecl) = NULL_TREE;
+ }
+
+ /* We hard-wired immediate_size_expand to zero above.
+ expand_function_end will decrement this variable. So, we set the
+ variable to one here, so that after the decrement it will remain
+ zero. */
+ immediate_size_expand = 1;
+
+ /* Allow language dialects to perform special processing. */
+ if (lang_expand_function_end)
+ (*lang_expand_function_end) ();
/* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 0);
- /* So we can tell if jump_optimize sets it to 1. */
- can_reach_end = 0;
+ /* 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 (nested_p)
+ ggc_push_context ();
/* Run the optimizers and output the assembler code for this function. */
rest_of_compilation (fndecl);
- current_function_returns_null |= can_reach_end;
-
- if (warn_missing_noreturn
- && !TREE_THIS_VOLATILE (fndecl)
- && !current_function_returns_null
- && !current_function_returns_value)
- warning ("function might be possible candidate for attribute `noreturn'");
-
- if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
- warning ("`noreturn' function does return");
- else if (warn_return_type && can_reach_end
- && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) != void_type_node)
- /* If this function returns non-void and control can drop through,
- complain. */
- warning ("control reaches end of non-void function");
+ /* Undo the GC context switch. */
+ if (nested_p)
+ ggc_pop_context ();
+
/* With just -W, complain only if function returns both with
and without a value. */
- else if (extra_warnings
- && current_function_returns_value && current_function_returns_null)
+ if (extra_warnings
+ && current_function_returns_value
+ && current_function_returns_null)
warning ("this function may return with or without a value");
/* If requested, warn about function definitions where the function will
@@ -7296,68 +7087,120 @@ finish_function (nested)
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 && 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))
{
- register tree ret_type_size = TYPE_SIZE (ret_type);
+ unsigned int size_as_int
+ = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
- if (TREE_CODE (ret_type_size) == INTEGER_CST)
- {
- unsigned units
- = TREE_INT_CST_LOW (ret_type_size) / BITS_PER_UNIT;
-
- if (units > larger_than_size)
- warning_with_decl (fndecl,
- "size of return value of `%s' is %u bytes",
- units);
- }
+ 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)
+ if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested_p
+ && ! flag_inline_trees)
{
- /* 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;
}
if (DECL_STATIC_CONSTRUCTOR (fndecl))
{
-#ifndef ASM_OUTPUT_CONSTRUCTOR
- if (! flag_gnu_linker)
- static_ctors = perm_tree_cons (NULL_TREE, fndecl, static_ctors);
+ if (targetm.have_ctors_dtors)
+ (* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
+ DEFAULT_INIT_PRIORITY);
else
-#endif
- assemble_constructor (IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+ static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
}
+
if (DECL_STATIC_DESTRUCTOR (fndecl))
{
-#ifndef ASM_OUTPUT_DESTRUCTOR
- if (! flag_gnu_linker)
- static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors);
+ if (targetm.have_ctors_dtors)
+ (* targetm.asm_out.destructor) (XEXP (DECL_RTL (fndecl), 0),
+ DEFAULT_INIT_PRIORITY);
else
-#endif
- assemble_destructor (IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+ static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
}
- if (! nested)
+ if (nested_p)
+ /* Return to the enclosing function. */
+ pop_function_context ();
+ timevar_pop (TV_EXPAND);
+}
+
+/* Check the declarations given in a for-loop for satisfying the C99
+ constraints. */
+void
+check_for_loop_decls ()
+{
+ tree t;
+
+ if (!flag_isoc99)
{
- /* Let the error reporting routines know that we're outside a
- function. For a nested function, this value is used in
- pop_c_function_context and then reset via pop_function_context. */
- current_function_decl = NULL;
+ /* If we get here, declarations have been used in a for loop without
+ the C99 for loop scope. This doesn't make much sense, so don't
+ allow it. */
+ error ("`for' loop initial declaration used outside C99 mode");
+ return;
+ }
+ /* C99 subclause 6.8.5 paragraph 3:
+
+ [#3] The declaration part of a for statement shall only
+ declare identifiers for objects having storage class auto or
+ register.
+
+ It isn't clear whether, in this sentence, "identifiers" binds to
+ "shall only declare" or to "objects" - that is, whether all identifiers
+ declared must be identifiers for objects, or whether the restriction
+ only applies to those that are. (A question on this in comp.std.c
+ in November 2000 received no answer.) We implement the strictest
+ interpretation, to avoid creating an extension which later causes
+ problems. */
+
+ 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");
}
}
@@ -7365,9 +7208,9 @@ finish_function (nested)
that keep track of the progress of compilation of the current function.
Used for nested functions. */
-struct c_function
+struct c_language_function
{
- struct c_function *next;
+ struct language_function base;
tree named_labels;
tree shadowed_labels;
int returns_value;
@@ -7377,25 +7220,20 @@ struct c_function
struct binding_level *binding_level;
};
-struct c_function *c_function_chain;
-
/* Save and reinitialize the variables
used during compilation of a C function. */
void
-push_c_function_context ()
+push_c_function_context (f)
+ struct function *f;
{
- struct c_function *p
- = (struct c_function *) xmalloc (sizeof (struct c_function));
-
- if (pedantic)
- pedwarn ("ANSI C forbids nested functions");
-
- push_function_context ();
-
- p->next = c_function_chain;
- c_function_chain = p;
+ 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;
@@ -7408,9 +7246,11 @@ push_c_function_context ()
/* Restore the variables used during compilation of a C function. */
void
-pop_c_function_context ()
+pop_c_function_context (f)
+ struct function *f;
{
- struct c_function *p = c_function_chain;
+ struct c_language_function *p
+ = (struct c_language_function *) f->language;
tree link;
/* Bring back all the labels that were shadowed. */
@@ -7419,7 +7259,8 @@ pop_c_function_context ()
IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
= TREE_VALUE (link);
- if (DECL_SAVED_INSNS (current_function_decl) == 0)
+ if (DECL_SAVED_INSNS (current_function_decl) == 0
+ && DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
{
/* Stop pointing to the local nodes about to be freed. */
/* But DECL_INITIAL must remain nonzero so we know this
@@ -7428,10 +7269,8 @@ pop_c_function_context ()
DECL_ARGUMENTS (current_function_decl) = 0;
}
- pop_function_context ();
-
- c_function_chain = p->next;
-
+ 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;
@@ -7441,13 +7280,181 @@ pop_c_function_context ()
current_binding_level = p->binding_level;
free (p);
+ f->language = 0;
}
-/* integrate_decl_tree calls this function, but since we don't use the
- DECL_LANG_SPECIFIC field, this is a no-op. */
+/* Mark the language specific parts of F for GC. */
void
-copy_lang_decl (node)
+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);
+}
+
+/* Copy the DECL_LANG_SPECIFIC data associated with NODE. */
+
+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));
+ memcpy ((char *) ld, (char *) DECL_LANG_SPECIFIC (decl),
+ sizeof (struct lang_decl));
+ DECL_LANG_SPECIFIC (decl) = ld;
+}
+
+/* Mark the language specific bits in T for GC. */
+
+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);
+ }
+}
+
+/* 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;
+}
+
+/* Returns the stmt_tree (if any) to which statements are currently
+ being added. If there is no active statement-tree, NULL is
+ returned. */
+
+stmt_tree
+current_stmt_tree ()
+{
+ return &c_stmt_tree;
+}
+
+/* Returns the stack of SCOPE_STMTs for the current function. */
+
+tree *
+current_scope_stmt_stack ()
+{
+ return &c_scope_stmt_stack;
+}
+
+/* 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;
+}
+
+/* Dummy function in place of callback used by C++. */
+
+void
+extract_interface_info ()
+{
+}
+
+/* Return a new COMPOUND_STMT, after adding it to the current
+ statement tree. */
+
+tree
+c_begin_compound_stmt ()
+{
+ tree stmt;
+
+ /* Create the COMPOUND_STMT. */
+ stmt = add_stmt (build_stmt (COMPOUND_STMT, NULL_TREE));
+
+ return stmt;
+}
+
+/* Expand T (a DECL_STMT) if it declares an entity not handled by the
+ common code. */
+
+void
+c_expand_decl_stmt (t)
+ tree t;
+{
+ tree decl = DECL_STMT_DECL (t);
+
+ /* Expand nested functions. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_CONTEXT (decl) == current_function_decl
+ && DECL_SAVED_TREE (decl))
+ c_expand_body (decl, /*nested_p=*/1, /*can_defer_p=*/0);
+}
+
+/* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since
+ the definition of IDENTIFIER_GLOBAL_VALUE is different for C and C++. */
+
+tree
+identifier_global_value (t)
+ tree t;
+{
+ return IDENTIFIER_GLOBAL_VALUE (t);
+}
+
+/* Record a builtin type for C. If NAME is non-NULL, it is the name used;
+ otherwise the name is found in ridpointers from RID_INDEX. */
+
+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));
+}
+
+/* Build the void_list_node (void_type_node having been created). */
+tree
+build_void_list_node ()
+{
+ tree t = build_tree_list (NULL_TREE, void_type_node);
+ return t;
}
OpenPOWER on IntegriCloud