/* Process declarations and variables for C compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001 Free Software Foundation, Inc.
+ 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "intl.h"
#include "tree.h"
#include "tree-inline.h"
#include "output.h"
#include "expr.h"
#include "c-tree.h"
-#include "c-lex.h"
#include "toplev.h"
#include "ggc.h"
#include "tm_p.h"
#include "target.h"
#include "debug.h"
#include "timevar.h"
+#include "c-common.h"
+#include "c-pragma.h"
+#include "cgraph.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
/* The current statement tree. */
-static struct stmt_tree_s c_stmt_tree;
+static GTY(()) struct stmt_tree_s c_stmt_tree;
/* The current scope statement stack. */
-static tree c_scope_stmt_stack;
+static GTY(()) 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. */
-static tree named_labels;
+static GTY(()) tree named_labels;
/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
-static tree shadowed_labels;
-
-/* Nonzero when store_parm_decls is called indicates a varargs function.
- Value not meaningful after store_parm_decls. */
-
-static int c_function_varargs;
+static GTY(()) tree shadowed_labels;
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
int current_function_returns_null;
+/* Set to 0 at beginning of a function definition, set to 1 if
+ a call to a noreturn function is seen. */
+
+int current_function_returns_abnormally;
+
/* Set to nonzero by `grokdeclarator' for a function
whose return type is defaulted, if warnings for this are desired. */
/* Note that the information in the `names' component of the global contour
is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
-struct binding_level
+struct binding_level GTY(())
{
/* A chain of _DECL nodes for all variables, constants, functions,
and typedef types. These are in the reverse of the order supplied.
/* Nonzero means make a BLOCK if this level has any subblocks. */
char keep_if_subblocks;
- /* Number of decls in `names' that have incomplete
- structure or union types. */
- int n_incomplete;
+ /* List of decls in `names' that have incomplete structure or
+ union types. */
+ tree incomplete_list;
/* A list of decls giving the (reversed) specified order of parms,
not including any forward-decls in the parmlist.
/* The binding level currently in effect. */
-static struct binding_level *current_binding_level;
+static GTY(()) struct binding_level *current_binding_level;
/* A chain of binding_level structures awaiting reuse. */
-static struct binding_level *free_binding_level;
+static GTY((deletable (""))) struct binding_level *free_binding_level;
/* The outermost binding level, for names of file scope.
This is created when the compiler is started and exists
through the entire run. */
-static struct binding_level *global_binding_level;
+static GTY(()) struct binding_level *global_binding_level;
/* Binding level structures are initialized by copying this one. */
static struct binding_level clear_binding_level
- = {NULL, NULL, NULL, NULL, NULL, NULL_BINDING_LEVEL, 0, 0, 0, 0, 0, 0,
+ = {NULL, NULL, NULL, NULL, NULL, NULL_BINDING_LEVEL, 0, 0, 0, 0, 0, NULL,
NULL};
/* Nonzero means unconditionally make a BLOCK for the next level pushed. */
saved values of named_labels and shadowed_labels for
a label binding level outside the current one. */
-static struct binding_level *label_level_chain;
+static GTY(()) struct binding_level *label_level_chain;
/* Functions called automatically at the beginning and end of execution. */
/* Forward declarations. */
static struct binding_level * make_binding_level PARAMS ((void));
-static void mark_binding_level PARAMS ((void *));
+static void pop_binding_level PARAMS ((struct binding_level **));
static void clear_limbo_values PARAMS ((tree));
static int duplicate_decls PARAMS ((tree, tree, int));
static int redeclaration_error_message PARAMS ((tree, 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 c_expand_body_1 PARAMS ((tree, int));
+static void warn_if_shadowing PARAMS ((tree, tree));
+static bool flexible_array_type_p PARAMS ((tree));
\f
-/* C-specific option variables. */
-
-/* Nonzero means allow type mismatches in conditional expressions;
- just make their values `void'. */
-
-int flag_cond_mismatch;
-
-/* Nonzero means don't recognize the keyword `asm'. */
-
-int flag_no_asm;
-
-/* Nonzero means do some things the same way PCC does. */
-
-int flag_traditional;
-
-/* Nonzero means enable C89 Amendment 1 features. */
-
-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'. */
-
-int flag_signed_bitfields = 1;
-int explicit_flag_signed_bitfields = 0;
-
-/* Nonzero means warn about use of implicit int. */
-
-int warn_implicit_int;
-
-/* Nonzero means warn about usage of long long when `-pedantic'. */
-
-int warn_long_long = 1;
-
-/* Nonzero means message about use of implicit function declarations;
- 1 means warning; 2 means error. */
-
-int mesg_implicit_function_declaration = -1;
-
-/* Nonzero means give string constants the type `const char *'
- to get extra warnings from them. These warnings will be too numerous
- to be useful, except in thoroughly ANSIfied programs. */
-
-int flag_const_strings;
-
-/* Nonzero means warn about pointer casts that can drop a type qualifier
- from the pointer target type. */
-
-int warn_cast_qual;
-
-/* Nonzero means warn when casting a function call to a type that does
- not match the return type (e.g. (float)sqrt() or (anything*)malloc()
- when there is no previous declaration of sqrt or malloc. */
-
-int warn_bad_function_cast;
-
-/* Warn about functions which might be candidates for format attributes. */
-
-int warn_missing_format_attribute;
-
-/* Warn about traditional constructs whose meanings changed in ANSI C. */
-
-int warn_traditional;
-
-/* Nonzero means warn about sizeof(function) or addition/subtraction
- of function pointers. */
-
-int warn_pointer_arith;
-
-/* Nonzero means warn for non-prototype function decls
- or non-prototyped defs without previous prototype. */
-
-int warn_strict_prototypes;
-
-/* Nonzero means warn for any global function def
- without separate previous prototype decl. */
-
-int warn_missing_prototypes;
-
-/* Nonzero means warn for any global function def
- without separate previous decl. */
-
-int warn_missing_declarations;
-
-/* Nonzero means warn about multiple (redundant) decls for the same single
- variable or function. */
-
-int warn_redundant_decls = 0;
-
-/* Nonzero means warn about extern declarations of objects not at
- file-scope level and about *all* declarations of functions (whether
- extern or static) not at file-scope level. Note that we exclude
- implicit function declarations. To get warnings about those, use
- -Wimplicit. */
-
-int warn_nested_externs = 0;
-
-/* Warn about a subscript that has type char. */
-
-int warn_char_subscripts = 0;
-
-/* Warn if a type conversion is done that might have confusing results. */
-
-int warn_conversion;
-
-/* Warn if adding () is suggested. */
-
-int warn_parentheses;
-
-/* Warn if initializer is not completely bracketed. */
-
-int warn_missing_braces;
-
-/* Warn if main is suspicious. */
-
-int warn_main;
-
-/* Warn about #pragma directives that are not recognised. */
-
-int warn_unknown_pragmas = 0; /* Tri state variable. */
-
-/* Warn about comparison of signed and unsigned values.
- If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified. */
-
-int warn_sign_compare = -1;
-
-/* 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;
-
-/* The variant of the C language being processed. */
-
-c_language_kind c_language = clk_c;
-
-/* Nonzero means `$' can be in an identifier. */
-
-#ifndef DOLLARS_IN_IDENTIFIERS
-#define DOLLARS_IN_IDENTIFIERS 1
-#endif
-int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
-
-/* Decode the string P as a language-specific option for C.
- Return the number of strings consumed. Should not complain
- if it does not recognise the option. */
-
-int
-c_decode_option (argc, argv)
- int argc ATTRIBUTE_UNUSED;
- char **argv;
-{
- int strings_processed;
- char *p = argv[0];
-
- strings_processed = cpp_handle_option (parse_in, argc, argv);
-
- if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
- {
- warning ("-traditional is deprecated and may be removed");
- flag_traditional = 1;
- flag_writable_strings = 1;
- }
- else if (!strcmp (p, "-fallow-single-precision"))
- flag_allow_single_precision = 1;
- else if (!strcmp (p, "-fhosted") || !strcmp (p, "-fno-freestanding"))
- {
- flag_hosted = 1;
- flag_no_builtin = 0;
- }
- else if (!strcmp (p, "-ffreestanding") || !strcmp (p, "-fno-hosted"))
- {
- flag_hosted = 0;
- flag_no_builtin = 1;
- /* warn_main will be 2 if set by -Wall, 1 if set by -Wmain */
- if (warn_main == 2)
- warn_main = 0;
- }
- else if (!strcmp (p, "-fnotraditional") || !strcmp (p, "-fno-traditional"))
- {
- flag_traditional = 0;
- flag_writable_strings = 0;
- }
- else if (!strncmp (p, "-std=", 5))
- {
- /* Select the appropriate language standard. We currently
- recognize:
- -std=iso9899:1990 same as -ansi
- -std=iso9899:199409 ISO C as modified in amend. 1
- -std=iso9899:1999 ISO C 99
- -std=c89 same as -std=iso9899:1990
- -std=c99 same as -std=iso9899:1999
- -std=gnu89 default, iso9899:1990 + gnu extensions
- -std=gnu99 iso9899:1999 + gnu extensions
- */
- const char *const argstart = &p[5];
-
- if (!strcmp (argstart, "iso9899:1990")
- || !strcmp (argstart, "c89"))
- {
- iso_1990:
- flag_isoc94 = 0;
- iso_1994:
- flag_traditional = 0;
- flag_writable_strings = 0;
- flag_no_asm = 1;
- flag_no_nonansi_builtin = 1;
- flag_noniso_default_format_attributes = 0;
- flag_isoc99 = 0;
- }
- else if (!strcmp (argstart, "iso9899:199409"))
- {
- flag_isoc94 = 1;
- goto iso_1994;
- }
- else if (!strcmp (argstart, "iso9899:199x")
- || !strcmp (argstart, "iso9899:1999")
- || !strcmp (argstart, "c9x")
- || !strcmp (argstart, "c99"))
- {
- flag_traditional = 0;
- flag_writable_strings = 0;
- flag_no_asm = 1;
- flag_no_nonansi_builtin = 1;
- flag_noniso_default_format_attributes = 0;
- flag_isoc99 = 1;
- flag_isoc94 = 1;
- }
- else if (!strcmp (argstart, "gnu89"))
- {
- flag_traditional = 0;
- flag_writable_strings = 0;
- flag_no_asm = 0;
- flag_no_nonansi_builtin = 0;
- flag_noniso_default_format_attributes = 1;
- flag_isoc99 = 0;
- flag_isoc94 = 0;
- }
- else if (!strcmp (argstart, "gnu9x") || !strcmp (argstart, "gnu99"))
- {
- flag_traditional = 0;
- flag_writable_strings = 0;
- flag_no_asm = 0;
- flag_no_nonansi_builtin = 0;
- flag_noniso_default_format_attributes = 1;
- flag_isoc99 = 1;
- flag_isoc94 = 1;
- }
- else
- error ("unknown C standard `%s'", argstart);
- }
- else if (!strcmp (p, "-fdollars-in-identifiers"))
- dollars_in_ident = 1;
- else if (!strcmp (p, "-fno-dollars-in-identifiers"))
- dollars_in_ident = 0;
- else if (!strcmp (p, "-fsigned-char"))
- flag_signed_char = 1;
- else if (!strcmp (p, "-funsigned-char"))
- flag_signed_char = 0;
- else if (!strcmp (p, "-fno-signed-char"))
- flag_signed_char = 0;
- else if (!strcmp (p, "-fno-unsigned-char"))
- flag_signed_char = 1;
- else if (!strcmp (p, "-fsigned-bitfields")
- || !strcmp (p, "-fno-unsigned-bitfields"))
- {
- flag_signed_bitfields = 1;
- explicit_flag_signed_bitfields = 1;
- }
- else if (!strcmp (p, "-funsigned-bitfields")
- || !strcmp (p, "-fno-signed-bitfields"))
- {
- flag_signed_bitfields = 0;
- explicit_flag_signed_bitfields = 1;
- }
- else if (!strcmp (p, "-fshort-enums"))
- flag_short_enums = 1;
- else if (!strcmp (p, "-fno-short-enums"))
- flag_short_enums = 0;
- else if (!strcmp (p, "-fshort-wchar"))
- flag_short_wchar = 1;
- else if (!strcmp (p, "-fno-short-wchar"))
- flag_short_wchar = 0;
- else if (!strcmp (p, "-fcond-mismatch"))
- flag_cond_mismatch = 1;
- else if (!strcmp (p, "-fno-cond-mismatch"))
- flag_cond_mismatch = 0;
- else if (!strcmp (p, "-fshort-double"))
- flag_short_double = 1;
- else if (!strcmp (p, "-fno-short-double"))
- flag_short_double = 0;
- else if (!strcmp (p, "-fasm"))
- flag_no_asm = 0;
- else if (!strcmp (p, "-fno-asm"))
- flag_no_asm = 1;
- else if (!strcmp (p, "-fbuiltin"))
- flag_no_builtin = 0;
- else if (!strcmp (p, "-fno-builtin"))
- flag_no_builtin = 1;
- else if (!strncmp (p, "-fno-builtin-", strlen ("-fno-builtin-")))
- disable_builtin_function (p + strlen ("-fno-builtin-"));
- else if (p[0] == '-' && p[1] == 'f' && dump_switch_p (p + 2))
- ;
- else if (!strcmp (p, "-ansi"))
- goto iso_1990;
- else if (!strcmp (p, "-Werror-implicit-function-declaration"))
- mesg_implicit_function_declaration = 2;
- else if (!strcmp (p, "-Wimplicit-function-declaration"))
- mesg_implicit_function_declaration = 1;
- else if (!strcmp (p, "-Wno-implicit-function-declaration"))
- mesg_implicit_function_declaration = 0;
- else if (!strcmp (p, "-Wimplicit-int"))
- warn_implicit_int = 1;
- else if (!strcmp (p, "-Wno-implicit-int"))
- warn_implicit_int = 0;
- else if (!strcmp (p, "-Wimplicit"))
- {
- warn_implicit_int = 1;
- if (mesg_implicit_function_declaration != 2)
- mesg_implicit_function_declaration = 1;
- }
- else if (!strcmp (p, "-Wno-implicit"))
- warn_implicit_int = 0, mesg_implicit_function_declaration = 0;
- else if (!strcmp (p, "-Wlong-long"))
- warn_long_long = 1;
- else if (!strcmp (p, "-Wno-long-long"))
- warn_long_long = 0;
- else if (!strcmp (p, "-Wwrite-strings"))
- flag_const_strings = 1;
- else if (!strcmp (p, "-Wno-write-strings"))
- flag_const_strings = 0;
- else if (!strcmp (p, "-Wcast-qual"))
- warn_cast_qual = 1;
- else if (!strcmp (p, "-Wno-cast-qual"))
- warn_cast_qual = 0;
- else if (!strcmp (p, "-Wbad-function-cast"))
- warn_bad_function_cast = 1;
- else if (!strcmp (p, "-Wno-bad-function-cast"))
- warn_bad_function_cast = 0;
- else if (!strcmp (p, "-Wno-missing-noreturn"))
- warn_missing_noreturn = 0;
- else if (!strcmp (p, "-Wmissing-format-attribute"))
- warn_missing_format_attribute = 1;
- else if (!strcmp (p, "-Wno-missing-format-attribute"))
- warn_missing_format_attribute = 0;
- else if (!strcmp (p, "-Wpointer-arith"))
- warn_pointer_arith = 1;
- else if (!strcmp (p, "-Wno-pointer-arith"))
- warn_pointer_arith = 0;
- else if (!strcmp (p, "-Wstrict-prototypes"))
- warn_strict_prototypes = 1;
- else if (!strcmp (p, "-Wno-strict-prototypes"))
- warn_strict_prototypes = 0;
- else if (!strcmp (p, "-Wmissing-prototypes"))
- warn_missing_prototypes = 1;
- else if (!strcmp (p, "-Wno-missing-prototypes"))
- warn_missing_prototypes = 0;
- else if (!strcmp (p, "-Wmissing-declarations"))
- warn_missing_declarations = 1;
- else if (!strcmp (p, "-Wno-missing-declarations"))
- warn_missing_declarations = 0;
- else if (!strcmp (p, "-Wredundant-decls"))
- warn_redundant_decls = 1;
- else if (!strcmp (p, "-Wno-redundant-decls"))
- warn_redundant_decls = 0;
- else if (!strcmp (p, "-Wnested-externs"))
- warn_nested_externs = 1;
- else if (!strcmp (p, "-Wno-nested-externs"))
- warn_nested_externs = 0;
- else if (!strcmp (p, "-Wtraditional"))
- warn_traditional = 1;
- else if (!strcmp (p, "-Wno-traditional"))
- warn_traditional = 0;
- else if (!strncmp (p, "-Wformat=", 9))
- set_Wformat (atoi (p + 9));
- else if (!strcmp (p, "-Wformat"))
- set_Wformat (1);
- else if (!strcmp (p, "-Wno-format"))
- set_Wformat (0);
- else if (!strcmp (p, "-Wformat-y2k"))
- warn_format_y2k = 1;
- else if (!strcmp (p, "-Wno-format-y2k"))
- warn_format_y2k = 0;
- else if (!strcmp (p, "-Wformat-extra-args"))
- warn_format_extra_args = 1;
- else if (!strcmp (p, "-Wno-format-extra-args"))
- warn_format_extra_args = 0;
- else if (!strcmp (p, "-Wformat-nonliteral"))
- warn_format_nonliteral = 1;
- else if (!strcmp (p, "-Wno-format-nonliteral"))
- warn_format_nonliteral = 0;
- else if (!strcmp (p, "-Wformat-security"))
- warn_format_security = 1;
- else if (!strcmp (p, "-Wno-format-security"))
- warn_format_security = 0;
- else if (!strcmp (p, "-Wchar-subscripts"))
- warn_char_subscripts = 1;
- else if (!strcmp (p, "-Wno-char-subscripts"))
- warn_char_subscripts = 0;
- else if (!strcmp (p, "-Wconversion"))
- warn_conversion = 1;
- else if (!strcmp (p, "-Wno-conversion"))
- warn_conversion = 0;
- else if (!strcmp (p, "-Wparentheses"))
- warn_parentheses = 1;
- else if (!strcmp (p, "-Wno-parentheses"))
- warn_parentheses = 0;
- else if (!strcmp (p, "-Wreturn-type"))
- warn_return_type = 1;
- else if (!strcmp (p, "-Wno-return-type"))
- warn_return_type = 0;
- else if (!strcmp (p, "-Wsequence-point"))
- warn_sequence_point = 1;
- else if (!strcmp (p, "-Wno-sequence-point"))
- warn_sequence_point = 0;
- else if (!strcmp (p, "-Wcomment"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wno-comment"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wcomments"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wno-comments"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wtrigraphs"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wno-trigraphs"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wundef"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wno-undef"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wimport"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wno-import"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wmissing-braces"))
- warn_missing_braces = 1;
- else if (!strcmp (p, "-Wno-missing-braces"))
- warn_missing_braces = 0;
- else if (!strcmp (p, "-Wmain"))
- warn_main = 1;
- else if (!strcmp (p, "-Wno-main"))
- warn_main = -1;
- else if (!strcmp (p, "-Wsign-compare"))
- warn_sign_compare = 1;
- else if (!strcmp (p, "-Wno-sign-compare"))
- warn_sign_compare = 0;
- else if (!strcmp (p, "-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. */
- warn_unknown_pragmas = 2;
- else if (!strcmp (p, "-Wno-unknown-pragmas"))
- warn_unknown_pragmas = 0;
- else if (!strcmp (p, "-Wall"))
- {
- /* We save the value of warn_uninitialized, since if they put
- -Wuninitialized on the command line, we need to generate a
- warning about not using it without also specifying -O. */
- if (warn_uninitialized != 1)
- warn_uninitialized = 2;
- warn_implicit_int = 1;
- mesg_implicit_function_declaration = 1;
- warn_return_type = 1;
- set_Wunused (1);
- warn_switch = 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. */
- warn_main = 2;
- /* Only warn about unknown pragmas that are not in system headers. */
- warn_unknown_pragmas = 1;
- }
- else
- return strings_processed;
+/* 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
+};
- return 1;
-}
+static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
void
c_print_identifier (file, node, indent)
for a top-level tentative array defn that wasn't complete before. */
void
-finish_incomplete_decl (decl)
+c_finish_incomplete_decl (decl)
tree decl;
{
if (TREE_CODE (decl) == VAR_DECL)
}
}
\f
-/* Create a new `struct binding_level'. */
+/* Reuse or create a struct for this binding level. */
static struct binding_level *
make_binding_level ()
{
- /* NOSTRICT */
- return (struct binding_level *) xmalloc (sizeof (struct binding_level));
+ if (free_binding_level)
+ {
+ struct binding_level *result = free_binding_level;
+ free_binding_level = result->level_chain;
+ return result;
+ }
+ else
+ return (struct binding_level *) ggc_alloc (sizeof (struct binding_level));
+}
+
+/* Remove a binding level from a list and add it to the level chain. */
+
+static void
+pop_binding_level (lp)
+ struct binding_level **lp;
+{
+ struct binding_level *l = *lp;
+ *lp = l->level_chain;
+
+ memset (l, 0, sizeof (struct binding_level));
+ l->level_chain = free_binding_level;
+ free_binding_level = l;
}
/* Nonzero if we are currently in the global binding level. */
named_labels = 0;
}
- /* Reuse or create a struct for this binding level. */
-
- if (free_binding_level)
- {
- newlevel = free_binding_level;
- free_binding_level = free_binding_level->level_chain;
- }
- else
- {
- newlevel = make_binding_level ();
- }
+ newlevel = make_binding_level ();
/* Add this level to the front of the chain (stack) of levels that
are active. */
/* Pop the current level, and free the structure for reuse. */
- {
- struct binding_level *level = current_binding_level;
- current_binding_level = current_binding_level->level_chain;
-
- level->level_chain = free_binding_level;
- free_binding_level = level;
- }
+ pop_binding_level (¤t_binding_level);
/* Dispose of the block that we just made inside some higher level. */
if (functionbody)
{
struct binding_level *newlevel;
- /* Reuse or create a struct for this binding level. */
-
- if (free_binding_level)
- {
- newlevel = free_binding_level;
- free_binding_level = free_binding_level->level_chain;
- }
- else
- {
- newlevel = make_binding_level ();
- }
+ newlevel = make_binding_level ();
/* Add this level to the front of the chain (stack) of label levels. */
shadowed_labels = level->shadowed;
/* Pop the current level, and free the structure for reuse. */
- label_level_chain = label_level_chain->level_chain;
- level->level_chain = free_binding_level;
- free_binding_level = level;
+ pop_binding_level (&label_level_chain);
}
\f
/* Push a definition or a declaration of struct, union or enum tag "name".
match enough. Ultimately, copy most of the information from the new
decl to the old one, and keep using the old one. */
- if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL
- && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (newdecl)) == olddecl
- && DECL_INITIAL (olddecl) == 0)
- /* If -traditional, avoid error for redeclaring fcn
- after implicit decl. */
- ;
- else if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_BUILT_IN (olddecl))
+ if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_BUILT_IN (olddecl))
{
/* A function declaration for a built-in function. */
if (!TREE_PUBLIC (newdecl))
if (! different_binding_level)
TREE_TYPE (olddecl) = oldtype;
}
+ else if (TYPE_ARG_TYPES (oldtype) == NULL
+ && TYPE_ARG_TYPES (newtype) != NULL)
+ {
+ /* For bcmp, bzero, fputs the builtin type has arguments not
+ specified. Use the ones from the prototype so that type checking
+ is done for them. */
+ tree trytype
+ = build_function_type (TREE_TYPE (oldtype),
+ TYPE_ARG_TYPES (newtype));
+ trytype = build_type_attribute_variant (trytype,
+ TYPE_ATTRIBUTES (oldtype));
+
+ oldtype = trytype;
+ if (! different_binding_level)
+ TREE_TYPE (olddecl) = oldtype;
+ }
if (!types_match)
{
/* If types don't match for a built-in, throw away the built-in. */
break;
}
- if (simple_type_promotes_to (type) != NULL_TREE)
+ if (c_type_promotes_to (type) != type)
{
error ("an argument type that has a default promotion can't match an empty parameter name list declaration");
break;
}
}
error_with_decl (olddecl, "previous declaration of `%s'");
+
+ /* This is safer because the initializer might contain references
+ to variables that were declared between olddecl and newdecl. This
+ will make the initializer invalid for olddecl in case it gets
+ assigned to olddecl below. */
+ if (TREE_CODE (newdecl) == VAR_DECL)
+ DECL_INITIAL (newdecl) = 0;
+ }
+ /* TLS cannot follow non-TLS declaration. */
+ else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
+ && !DECL_THREAD_LOCAL (olddecl) && DECL_THREAD_LOCAL (newdecl))
+ {
+ error_with_decl (newdecl, "thread-local declaration of `%s' follows non thread-local declaration");
+ error_with_decl (olddecl, "previous declaration of `%s'");
+ }
+ /* non-TLS declaration cannot follow TLS declaration. */
+ else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
+ && DECL_THREAD_LOCAL (olddecl) && !DECL_THREAD_LOCAL (newdecl))
+ {
+ error_with_decl (newdecl, "non thread-local declaration of `%s' follows thread-local declaration");
+ error_with_decl (olddecl, "previous declaration of `%s'");
}
else
{
&& current_binding_level == global_binding_level)
? "`%s' previously defined here"
: "`%s' previously declared here"));
+ return 0;
}
else if (TREE_CODE (newdecl) == TYPE_DECL
&& (DECL_IN_SYSTEM_HEADER (olddecl)
}
/* Type for passing arg must be consistent
with that declared for the arg. */
- if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type))
- /* If -traditional, allow `unsigned int' instead of `int'
- in the prototype. */
- && (! (flag_traditional
- && TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == integer_type_node
- && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node)))
+ if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type)))
{
error_with_decl (newdecl,
"prototype for `%s' follows and argument %d doesn't match",
COPY_DECL_RTL (olddecl, newdecl);
/* Merge the type qualifiers. */
- 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;
{
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);
- DECL_NO_LIMIT_STACK (newdecl)
- |= DECL_NO_LIMIT_STACK (olddecl);
}
}
/* If cannot merge, then use the new type and qualifiers,
}
/* Merge the storage class information. */
- DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);
+ merge_weak (newdecl, olddecl);
+
/* For functions, static overrides non-static. */
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
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))
+ if (new_is_definition && DECL_INITIAL (olddecl))
{
- (*debug_hooks->outlining_inline_function) (olddecl);
+ if (TREE_USED (olddecl))
+ (*debug_hooks->outlining_inline_function) (olddecl);
/* The new defn must not be inline. */
DECL_INLINE (newdecl) = 0;
/* 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) == 0)
- DECL_DECLARED_INLINE_P (olddecl) = 1;
-
- DECL_DECLARED_INLINE_P (newdecl) = DECL_DECLARED_INLINE_P (olddecl);
+ || DECL_DECLARED_INLINE_P (olddecl))
+ DECL_DECLARED_INLINE_P (newdecl) = 1;
DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
}
}
+
/* Also preserve various other info from the definition. */
- else if (! new_is_definition)
- DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
if (! new_is_definition)
{
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
DECL_INITIAL, so that we don't accidentally change function
declarations into function definitions. */
if (! different_binding_level)
- {
- DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
- DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
- }
+ 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_ABSTRACT_ORIGIN (olddecl);
+
+ /* 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
+ {
+ /* 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 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).
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)
+ if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x))
{
- t = lookup_name (name);
+ t = IDENTIFIER_GLOBAL_VALUE (name);
/* Type decls at global scope don't conflict with externs declared
inside lexical blocks. */
- if (t && TREE_CODE (t) == TYPE_DECL)
- t = 0;
+ if (! t || TREE_CODE (t) == TYPE_DECL)
+ /* If there's no visible global declaration, try for an
+ invisible one. */
+ t = IDENTIFIER_LIMBO_VALUE (name);
different_binding_level = 1;
}
if (t != 0 && t == error_mark_node)
}
/* If this decl is `static' and an implicit decl was seen previously,
- warn. But don't complain if -traditional,
- since traditional compilers don't complain. */
- if (! flag_traditional && TREE_PUBLIC (name)
+ warn. */
+ if (TREE_PUBLIC (name)
/* Don't test for DECL_EXTERNAL, because grokdeclarator
sets this for all functions. */
&& ! TREE_PUBLIC (x)
}
/* If we are processing a typedef statement, generate a whole new
- ..._TYPE node (which will be just an variant of the existing
+ ..._TYPE node (which will be just a variant of the existing
..._TYPE node with identical properties) and then install the
TYPE_DECL node generated to represent the typedef name as the
TYPE_NAME of this brand new (duplicate) ..._TYPE node.
}
/* Multiple external decls of the same identifier ought to match.
- Check against both global declarations (when traditional) and out of
- scope (limbo) block level declarations.
-
We get warnings about inline functions where they are defined.
Avoid duplicate warnings where they are used. */
if (TREE_PUBLIC (x)
{
tree decl;
- if (flag_traditional && IDENTIFIER_GLOBAL_VALUE (name) != 0
- && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name))
- || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name))))
- decl = IDENTIFIER_GLOBAL_VALUE (name);
- else if (IDENTIFIER_LIMBO_VALUE (name) != 0)
+ if (IDENTIFIER_LIMBO_VALUE (name) != 0)
/* Decls in limbo are always extern, so no need to check that. */
decl = IDENTIFIER_LIMBO_VALUE (name);
else
"previous implicit declaration of `%s'");
}
- /* In PCC-compatibility mode, extern decls of vars with no current decl
- take effect at top level no matter where they are. */
- if (flag_traditional && DECL_EXTERNAL (x)
- && lookup_name (name) == 0)
- {
- tree type = TREE_TYPE (x);
-
- /* But don't do this if the type contains temporary nodes. */
- while (type)
- {
- if (type == error_mark_node)
- break;
- if (TYPE_CONTEXT (type))
- {
- warning_with_decl (x, "type of external `%s' is not global");
- /* By exiting the loop early, we leave TYPE nonzero,
- and thus prevent globalization of the decl. */
- break;
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE
- && TYPE_ARG_TYPES (type) != 0)
- /* The types might not be truly local,
- but the list of arg types certainly is temporary.
- Since prototypes are nontraditional,
- ok not to do the traditional thing. */
- break;
- type = TREE_TYPE (type);
- }
-
- if (type == 0)
- b = global_binding_level;
- }
-
/* This name is new in its binding level.
Install the new declaration and return it. */
if (b == global_binding_level)
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))
- {
- const 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. */
b->shadowed = tree_cons (name, oldlocal, b->shadowed);
}
- /* Keep count of variables in this level with incomplete type.
+ /* Keep list of variables in this level with incomplete type.
If the input is erroneous, we can have error_mark in the type
slot (e.g. "f(void a, ...)") - that doesn't count as an
incomplete type. */
if (TREE_TYPE (x) != error_mark_node
&& !COMPLETE_TYPE_P (TREE_TYPE (x)))
- ++b->n_incomplete;
+ {
+ tree element = TREE_TYPE (x);
+
+ while (TREE_CODE (element) == ARRAY_TYPE)
+ element = TREE_TYPE (element);
+ if (TREE_CODE (element) == RECORD_TYPE
+ || TREE_CODE (element) == UNION_TYPE)
+ b->incomplete_list = tree_cons (NULL_TREE, x, b->incomplete_list);
+ }
}
/* Put decls on list in reverse order.
IDENTIFIER_IMPLICIT_DECL (functionid) = decl;
/* ANSI standard says implicit declarations are in the innermost block.
- So we record the decl in the standard fashion.
- If flag_traditional is set, pushdecl does it top-level. */
+ So we record the decl in the standard fashion. */
pushdecl (decl);
- /* This is a no-op in c-lang.c or something real in objc-actions.c. */
- maybe_objc_check_decl (decl);
+ /* This is a no-op in c-lang.c or something real in objc-act.c. */
+ if (flag_objc)
+ objc_check_decl (decl);
rest_of_decl_compilation (decl, NULL, 0, 0);
{
if (TREE_CODE (newdecl) == TYPE_DECL)
{
- if (flag_traditional && TREE_TYPE (newdecl) == TREE_TYPE (olddecl))
- return 0;
- /* pushdecl creates distinct types for TYPE_DECLs by calling
- build_type_copy, so the above comparison generally fails. We do
- another test against the TYPE_MAIN_VARIANT of the olddecl, which
- is equivalent to what this code used to do before the build_type_copy
- call. The variant type distinction should not matter for traditional
- code, because it doesn't have type qualifiers. */
- if (flag_traditional
- && TYPE_MAIN_VARIANT (TREE_TYPE (olddecl)) == TREE_TYPE (newdecl))
- return 0;
+ /* Do not complain about type redeclarations where at least one
+ declaration was in a system header. */
if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl))
return 0;
return 1;
return t;
}
\f
-/* 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.
boolean_true_node = integer_one_node;
boolean_false_node = integer_zero_node;
- /* With GCC, C99's _Bool is always of size 1. */
- c_bool_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
+ c_bool_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
TREE_SET_CODE (c_bool_type_node, BOOLEAN_TYPE);
TYPE_MAX_VALUE (c_bool_type_node) = build_int_2 (1, 0);
TREE_TYPE (TYPE_MAX_VALUE (c_bool_type_node)) = c_bool_type_node;
= build_function_type (ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node, endlink));
- /* Types which are common to the fortran compiler and libf2c. When
- changing these, you also need to be concerned with f/com.h. */
-
- if (TYPE_PRECISION (float_type_node)
- == TYPE_PRECISION (long_integer_type_node))
- {
- g77_integer_type_node = long_integer_type_node;
- g77_uinteger_type_node = long_unsigned_type_node;
- }
- else if (TYPE_PRECISION (float_type_node)
- == TYPE_PRECISION (integer_type_node))
- {
- g77_integer_type_node = integer_type_node;
- g77_uinteger_type_node = unsigned_type_node;
- }
- else
- g77_integer_type_node = g77_uinteger_type_node = NULL_TREE;
-
- if (g77_integer_type_node != NULL_TREE)
- {
- pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_integer"),
- g77_integer_type_node));
- pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_uinteger"),
- g77_uinteger_type_node));
- }
-
- if (TYPE_PRECISION (float_type_node) * 2
- == TYPE_PRECISION (long_integer_type_node))
- {
- g77_longint_type_node = long_integer_type_node;
- g77_ulongint_type_node = long_unsigned_type_node;
- }
- else if (TYPE_PRECISION (float_type_node) * 2
- == TYPE_PRECISION (long_long_integer_type_node))
- {
- g77_longint_type_node = long_long_integer_type_node;
- g77_ulongint_type_node = long_long_unsigned_type_node;
- }
- else
- g77_longint_type_node = g77_ulongint_type_node = NULL_TREE;
-
- if (g77_longint_type_node != NULL_TREE)
- {
- pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_longint"),
- g77_longint_type_node));
- pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_ulongint"),
- g77_ulongint_type_node));
- }
-
pedantic_lvalues = pedantic;
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
-
- incomplete_decl_finalize_hook = finish_incomplete_decl;
-
- /* 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 (¤t_binding_level, 1, sizeof current_binding_level,
- mark_binding_level);
- ggc_add_root (&label_level_chain, 1, sizeof label_level_chain,
- mark_binding_level);
- ggc_add_tree_root (&static_ctors, 1);
- ggc_add_tree_root (&static_dtors, 1);
}
/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
DECL_INITIAL (decl) = init;
TREE_USED (decl) = 1;
+
+ if (current_function_decl)
+ {
+ /* Add the decls to the outermost block. */
+ struct binding_level *b = current_binding_level;
+ struct binding_level *old = b;
+ while (b->level_chain->parm_flag == 0)
+ b = b->level_chain;
+ current_binding_level = b;
+ pushdecl (decl);
+ current_binding_level = old;
+ }
finish_decl (decl, init, NULL_TREE);
See tree.h for its possible values.
If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
- the name to be called if we can't opencode the function. */
+ the name to be called if we can't opencode the function. If
+ ATTRS is nonzero, use that for the function's attribute list. */
tree
-builtin_function (name, type, function_code, class, library_name)
+builtin_function (name, type, function_code, class, library_name, attrs)
const char *name;
tree type;
int function_code;
enum built_in_class class;
const char *library_name;
+ tree attrs;
{
tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
- /* If -traditional, permit redefining a builtin function any way you like.
- (Though really, if the program redefines these functions,
- it probably won't work right unless compiled with -fno-builtin.) */
- if (flag_traditional && name[0] != '_')
- DECL_BUILT_IN_NONANSI (decl) = 1;
if (library_name)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
make_decl_rtl (decl, NULL);
C_DECL_ANTICIPATED (decl) = 1;
/* Possibly apply some default attributes to this built-in function. */
- decl_attributes (&decl, NULL_TREE, 0);
+ if (attrs)
+ decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
+ else
+ decl_attributes (&decl, NULL_TREE, 0);
return decl;
}
attributes. */
void
-insert_default_attributes (decl)
+c_insert_default_attributes (decl)
tree decl;
{
if (!TREE_PUBLIC (decl))
/* 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
+ nonzero if "static" is inside the [], zero otherwise. VLA_UNSPEC_P
+ is nonzero 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
if (pedantic && !flag_isoc99)
{
if (static_p || quals != NULL_TREE)
- pedwarn ("ISO C89 does not support `static' or type qualifiers in parameter array declarators");
+ pedwarn ("ISO C90 does not support `static' or type qualifiers in parameter array declarators");
if (vla_unspec_p)
- pedwarn ("ISO C89 does not support `[*]' array declarators");
+ pedwarn ("ISO C90 does not support `[*]' array declarators");
}
if (vla_unspec_p)
warning ("GCC does not yet properly implement `[*]' array declarators");
/* 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
+ of the [] and goes in operand 0. ABSTRACT_P is nonzero 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. */
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);
+
+ /* Apply attributes. */
+ decl_attributes (&typename, attrs, 0);
+
+ return typename;
}
/* Return a PARM_DECL node for a given pair of specs and declarator. */
int initialized;
tree attributes;
{
- tree decl = grokdeclarator (declarator, declspecs,
- NORMAL, 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;
+
+ decl = grokdeclarator (declarator, declspecs,
+ NORMAL, initialized);
+
+ deprecated_state = DEPRECATED_NORMAL;
if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
&& MAIN_NAME_P (DECL_NAME (decl)))
switch (TREE_CODE (decl))
{
case TYPE_DECL:
- /* typedef foo = bar means give foo the same type as bar.
- We haven't parsed bar yet, so `finish_decl' will fix that up.
- Any other case of an initialization in a TYPE_DECL is an error. */
- if (pedantic || list_length (declspecs) > 1)
- {
- error ("typedef `%s' is initialized",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- initialized = 0;
- }
+ error ("typedef `%s' is initialized (use __typeof__ instead)",
+ IDENTIFIER_POINTER (DECL_NAME (decl)));
+ initialized = 0;
break;
case FUNCTION_DECL:
/* ANSI specifies that a tentative definition which is not merged with
a non-tentative definition behaves exactly like a definition with an
initializer equal to zero. (Section 3.7.2)
- -fno-common gives strict ANSI behavior. Usually you don't want it.
- This matters only for variables with external linkage. */
- if (! flag_no_common || ! TREE_PUBLIC (decl))
+
+ -fno-common gives strict ANSI behavior, though this tends to break
+ a large body of code that grew up without this rule.
+
+ Thread-local variables are never common, since there's no entrenched
+ body of code to break, and it allows more efficient variable references
+ in the presence of dynamic linking. */
+
+ if (TREE_CODE (decl) == VAR_DECL
+ && !initialized
+ && TREE_PUBLIC (decl)
+ && !DECL_THREAD_LOCAL (decl)
+ && !flag_no_common)
DECL_COMMON (decl) = 1;
/* Set attributes here so if duplicate decl, will have proper attributes. */
decl_attributes (&decl, attributes, 0);
+ /* If #pragma weak was used, mark the decl weak now. */
+ if (current_binding_level == global_binding_level)
+ maybe_apply_pragma_weak (decl);
+
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
const char *asmspec = 0;
/* If a name was specified, get the string. */
+ if (current_binding_level == global_binding_level)
+ asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
init = 0;
if (init)
- {
- if (TREE_CODE (decl) != TYPE_DECL)
- store_init_value (decl, init);
- else
- {
- /* typedef foo = bar; store the type of bar as the type of foo. */
- TREE_TYPE (decl) = TREE_TYPE (init);
- DECL_INITIAL (decl) = init = 0;
- }
- }
+ store_init_value (decl, init);
/* Deduce size of array from initialization, if not already known */
if (TREE_CODE (type) == ARRAY_TYPE
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
{
- /* This is a no-op in c-lang.c or something real in objc-actions.c. */
- maybe_objc_check_decl (decl);
+ /* This is a no-op in c-lang.c or something real in objc-act.c. */
+ if (flag_objc)
+ objc_check_decl (decl);
if (!DECL_CONTEXT (decl))
{
if (TREE_CODE (decl) == TYPE_DECL)
{
- /* This is a no-op in c-lang.c or something real in objc-actions.c. */
- maybe_objc_check_decl (decl);
+ /* This is a no-op in c-lang.c or something real in objc-act.c. */
+ if (flag_objc)
+ objc_check_decl (decl);
rest_of_decl_compilation (decl, NULL, DECL_CONTEXT (decl) == 0, 0);
}
get_pending_sizes ();
}
-/* If DECL has a cleanup, build and return that cleanup here.
- This is a callback called by expand_expr. */
-
-tree
-maybe_build_cleanup (decl)
- tree decl ATTRIBUTE_UNUSED;
-{
- /* There are no cleanups in C. */
- return NULL_TREE;
-}
-
/* Given a parsed parameter declaration,
decode it into a PARM_DECL and push that on the current binding level.
Also, for the sake of forward parm decls,
current_binding_level->parm_order = NULL_TREE;
}
\f
+static GTY(()) int compound_literal_number;
+
+/* 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;
+ TREE_READONLY (decl) = TREE_READONLY (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. */
+ char *name;
+
+ ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal",
+ compound_literal_number);
+ compound_literal_number++;
+ DECL_NAME (decl) = get_identifier (name);
+ DECL_DEFER_OUTPUT (decl) = 1;
+ DECL_COMDAT (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
+ pushdecl (decl);
+ rest_of_decl_compilation (decl, NULL, 1, 0);
+ }
+
+ return complit;
+}
+\f
/* 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). */
return value;
}
\f
+/* Determine whether TYPE is a structure with a flexible array member,
+ or a union containing such a structure (possibly recursively). */
+
+static bool
+flexible_array_type_p (type)
+ tree type;
+{
+ tree x;
+ switch (TREE_CODE (type))
+ {
+ case RECORD_TYPE:
+ x = TYPE_FIELDS (type);
+ if (x == NULL_TREE)
+ return false;
+ while (TREE_CHAIN (x) != NULL_TREE)
+ x = TREE_CHAIN (x);
+ 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)
+ return true;
+ return false;
+ case UNION_TYPE:
+ for (x = TYPE_FIELDS (type); x != NULL_TREE; x = TREE_CHAIN (x))
+ {
+ if (flexible_array_type_p (TREE_TYPE (x)))
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+\f
/* Given declspecs and a declarator,
determine the name and type of the object declared
and construct a ..._DECL node for it.
{
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])
enum rid i = C_RID_CODE (id);
if ((int) i <= (int) RID_LAST_MODIFIER)
{
- if (i == RID_LONG && (specbits & (1 << (int) i)))
+ if (i == RID_LONG && (specbits & (1 << (int) RID_LONG)))
{
if (longlong)
error ("`long long long' is too long for GCC");
{
if (pedantic && !flag_isoc99 && ! in_system_header
&& warn_long_long)
- pedwarn ("ISO C89 does not support `long long'");
+ pedwarn ("ISO C90 does not support `long long'");
longlong = 1;
}
}
else if (specbits & (1 << (int) i))
- pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
+ {
+ if (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT)
+ {
+ if (!flag_isoc99)
+ pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
+ }
+ else
+ error ("duplicate `%s'", IDENTIFIER_POINTER (id));
+ }
+
+ /* Diagnose "__thread extern". Recall that this list
+ is in the reverse order seen in the text. */
+ if (i == RID_THREAD
+ && (specbits & (1 << (int) RID_EXTERN
+ | 1 << (int) RID_STATIC)))
+ {
+ if (specbits & 1 << (int) RID_EXTERN)
+ error ("`__thread' before `extern'");
+ else
+ error ("`__thread' before `static'");
+ }
+
specbits |= 1 << (int) i;
goto found;
}
/* Actual typedefs come to us as TYPE_DECL nodes. */
else if (TREE_CODE (id) == TYPE_DECL)
{
- type = TREE_TYPE (id);
- decl_attr = DECL_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)
else
{
ok = 1;
- if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
+ if (!explicit_int && !defaulted_int && !explicit_char)
{
- pedwarn ("long, short, signed or unsigned used invalidly for `%s'",
- name);
- if (flag_pedantic_errors)
- ok = 0;
+ error ("long, short, signed or unsigned used invalidly for `%s'",
+ name);
+ ok = 0;
}
}
/* Decide whether an integer type is signed or not.
Optionally treat bitfields as signed by default. */
if (specbits & 1 << (int) RID_UNSIGNED
- /* Traditionally, all bitfields are unsigned. */
- || (bitfield && flag_traditional
- && (! explicit_flag_signed_bitfields || !flag_signed_bitfields))
|| (bitfield && ! flag_signed_bitfields
&& (explicit_int || defaulted_int || explicit_char
/* A typedef for plain `int' without `signed'
else if (type == char_type_node)
type = unsigned_char_type_node;
else if (typedef_decl)
- type = unsigned_type (type);
+ type = c_common_unsigned_type (type);
else
type = unsigned_type_node;
}
if (specbits & 1 << (int) RID_COMPLEX)
{
if (pedantic && !flag_isoc99)
- pedwarn ("ISO C89 does not support complex types");
+ pedwarn ("ISO C90 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
if (specbits & 1 << (int) RID_REGISTER) nclasses++;
if (specbits & 1 << (int) RID_TYPEDEF) nclasses++;
+ /* "static __thread" and "extern __thread" are allowed. */
+ if ((specbits & (1 << (int) RID_THREAD
+ | 1 << (int) RID_STATIC
+ | 1 << (int) RID_EXTERN)) == (1 << (int) RID_THREAD))
+ nclasses++;
+
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
&& (specbits
& ((1 << (int) RID_REGISTER)
| (1 << (int) RID_AUTO)
- | (1 << (int) RID_TYPEDEF))))
+ | (1 << (int) RID_TYPEDEF)
+ | (1 << (int) RID_THREAD))))
{
if (specbits & 1 << (int) RID_AUTO
&& (pedantic || current_binding_level == global_binding_level))
error ("function definition declared `register'");
if (specbits & 1 << (int) RID_TYPEDEF)
error ("function definition declared `typedef'");
+ if (specbits & 1 << (int) RID_THREAD)
+ error ("function definition declared `__thread'");
specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
- | (1 << (int) RID_AUTO));
+ | (1 << (int) RID_AUTO) | (1 << (int) RID_THREAD));
}
else if (decl_context != NORMAL && nclasses > 0)
{
}
specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
| (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
- | (1 << (int) RID_EXTERN));
+ | (1 << (int) RID_EXTERN) | (1 << (int) RID_THREAD));
}
}
else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
else
error ("`%s' has both `extern' and initializer", name);
}
- else if (specbits & 1 << (int) RID_EXTERN && funcdef_flag
- && current_binding_level != global_binding_level)
- error ("nested function `%s' declared `extern'", name);
- else if (current_binding_level == global_binding_level
- && specbits & (1 << (int) RID_AUTO))
- error ("top-level declaration of `%s' specifies `auto'", name);
+ else if (current_binding_level == global_binding_level)
+ {
+ if (specbits & 1 << (int) RID_AUTO)
+ error ("top-level declaration of `%s' specifies `auto'", name);
+ }
+ else
+ {
+ if (specbits & 1 << (int) RID_EXTERN && funcdef_flag)
+ error ("nested function `%s' declared `extern'", name);
+ else if ((specbits & (1 << (int) RID_THREAD
+ | 1 << (int) RID_EXTERN
+ | 1 << (int) RID_STATIC))
+ == (1 << (int) RID_THREAD))
+ {
+ error ("function-scope `%s' implicitly auto and declared `__thread'",
+ name);
+ specbits &= ~(1 << (int) RID_THREAD);
+ }
+ }
}
/* Now figure out the structure of the declarator proper.
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)
+ else if (TREE_CODE (inner_decl) == CALL_EXPR)
attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
- if (TREE_CODE (inner_decl) == ARRAY_REF)
+ else if (TREE_CODE (inner_decl) == ARRAY_REF)
attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
returned_attrs = decl_attributes (&type,
chainon (returned_attrs, attrs),
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);
+ tree index_type = c_common_signed_type (sizetype);
array_ptr_quals = TREE_TYPE (declarator);
array_parm_static = TREE_STATIC (declarator);
type = error_mark_node;
}
+ if (pedantic && flexible_array_type_p (type))
+ pedwarn ("invalid use of structure with flexible array member");
+
if (size == error_mark_node)
type = error_mark_node;
even if it is (eg) a const variable with known value. */
size_varies = 1;
- if (pedantic)
+ if (!flag_isoc99 && pedantic)
{
if (TREE_CONSTANT (size))
- pedwarn ("ISO C89 forbids array `%s' whose size can't be evaluated",
+ pedwarn ("ISO C90 forbids array `%s' whose size can't be evaluated",
name);
else
- pedwarn ("ISO C89 forbids variable-size array `%s'",
+ pedwarn ("ISO C90 forbids variable-size array `%s'",
name);
}
}
}
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 (pedantic && !flag_isoc99 && !in_system_header)
- pedwarn ("ISO C89 does not support flexible array members");
+ pedwarn ("ISO C90 does not support flexible array members");
/* ISO C99 Flexible array members are effectively identical
to GCC's zero-length array extension. */
type = integer_type_node;
}
-#ifndef TRADITIONAL_RETURN_FLOAT
- /* Traditionally, declaring return type float means double. */
-
- if (flag_traditional && TYPE_MAIN_VARIANT (type) == float_type_node)
- type = double_type_node;
-#endif /* TRADITIONAL_RETURN_FLOAT */
-
/* Construct the function type and go to the next
inner layer of declarator. */
{
/* 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
+ warning at -Wextra. 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
if (type == error_mark_node)
promoted_type = type;
else
- {
- promoted_type = simple_type_promotes_to (type);
- if (! promoted_type)
- promoted_type = type;
- }
+ promoted_type = c_type_promotes_to (type);
DECL_ARG_TYPE (decl) = promoted_type;
DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written;
pedwarn ("invalid storage class for function `%s'", name);
if (specbits & (1 << (int) RID_REGISTER))
error ("invalid storage class for function `%s'", name);
+ if (specbits & (1 << (int) RID_THREAD))
+ error ("invalid storage class for function `%s'", name);
/* Function declaration not at top level.
Storage classes other than `extern' are not allowed
and `extern' makes no difference. */
TREE_PUBLIC (decl)
= !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
+ if (defaulted_int)
+ C_FUNCTION_IMPLICIT_INT (decl) = 1;
+
/* Record presence of `inline', if it is reasonable. */
if (MAIN_NAME_P (declarator))
{
else if (inlinep)
{
/* Assume that otherwise the function can be inlined. */
- DECL_INLINE (decl) = 1;
DECL_DECLARED_INLINE_P (decl) = 1;
- if (specbits & (1 << (int) RID_EXTERN))
- current_extern_inline = 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)
+ else if (flag_inline_trees == 2 && initialized)
{
+ if (!DECL_INLINE (decl))
+ DID_INLINE_FUNC (decl) = 1;
DECL_INLINE (decl) = 1;
DECL_DECLARED_INLINE_P (decl) = 0;
}
pedwarn_with_decl (decl, "variable `%s' declared `inline'");
DECL_EXTERNAL (decl) = extern_ref;
+
/* At top level, the presence of a `static' or `register' storage
class specifier, or the absence of all storage class specifiers
makes this declaration a definition (perhaps tentative). Also,
the absence of both `static' and `register' makes it public. */
if (current_binding_level == global_binding_level)
{
- TREE_PUBLIC (decl)
- = !(specbits
- & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)));
- TREE_STATIC (decl) = ! DECL_EXTERNAL (decl);
+ TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC)
+ | (1 << (int) RID_REGISTER)));
+ TREE_STATIC (decl) = !extern_ref;
}
/* Not at top level, only `static' makes a static definition. */
else
{
TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
- TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
+ TREE_PUBLIC (decl) = extern_ref;
+ }
+
+ if (specbits & 1 << (int) RID_THREAD)
+ {
+ if (targetm.have_tls)
+ DECL_THREAD_LOCAL (decl) = 1;
+ else
+ /* A mere warning is sure to result in improper semantics
+ at runtime. Don't bother to allow this to compile. */
+ error ("thread-local storage not supported for this target");
}
}
Otherwise, the fact that those components are volatile
will be ignored, and would even crash the compiler. */
if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
- mark_addressable (decl);
+ c_mark_addressable (decl);
decl_attributes (&decl, returned_attrs, 0);
ref = lookup_tag (code, name, current_binding_level, 1);
if (ref && TREE_CODE (ref) == code)
{
- C_TYPE_BEING_DEFINED (ref) = 1;
- TYPE_PACKED (ref) = flag_pack_struct;
if (TYPE_FIELDS (ref))
{
if (code == UNION_TYPE)
- error ("redefinition of `union %s'",
- IDENTIFIER_POINTER (name));
+ error ("redefinition of `union %s'", IDENTIFIER_POINTER (name));
else
- error ("redefinition of `struct %s'",
- IDENTIFIER_POINTER (name));
+ error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name));
}
-
- return ref;
}
+ else
+ {
+ /* Otherwise create a forward-reference just so the tag is in scope. */
- /* Otherwise create a forward-reference just so the tag is in scope. */
-
- ref = make_node (code);
- pushtag (name, ref);
+ ref = make_node (code);
+ pushtag (name, ref);
+ }
+
C_TYPE_BEING_DEFINED (ref) = 1;
TYPE_PACKED (ref) = flag_pack_struct;
return ref;
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)
+ /* This is an unnamed decl.
+
+ If we have something of the form "union { list } ;" then this
+ is the anonymous union extension. Similarly for struct.
+
+ If this is something of the form "struct foo;", then
+ If MS extensions are enabled, this is handled as an
+ anonymous struct.
+ Otherwise this is a forward declaration of a structure tag.
+
+ If this is something of the form "foo;" and foo is a TYPE_DECL, then
+ If MS extensions are enabled and foo names a structure, then
+ again this is an anonymous struct.
+ Otherwise this is an error.
+
+ Oh what a horrid tangled web we weave. I wonder if MS consciously
+ took this from Plan 9 or if it was an accident of implementation
+ that took root before someone noticed the bug... */
+
+ tree type = TREE_VALUE (declspecs);
+
+ if (flag_ms_extensions && TREE_CODE (type) == TYPE_DECL)
+ type = TREE_TYPE (type);
+ if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)
{
- error ("unnamed fields of type other than struct or union are not allowed");
+ if (flag_ms_extensions)
+ ; /* ok */
+ else if (flag_iso)
+ goto warn_unnamed_field;
+ else if (TYPE_NAME (type) == NULL)
+ ; /* ok */
+ else
+ goto warn_unnamed_field;
+ }
+ else
+ {
+ warn_unnamed_field:
+ warning ("declaration does not declare anything");
return NULL_TREE;
}
}
finish_decl (value, NULL_TREE, NULL_TREE);
DECL_INITIAL (value) = width;
- maybe_objc_check_decl (value);
+ if (flag_objc)
+ objc_check_decl (value);
return value;
}
\f
if (pedantic)
pedwarn ("%s defined inside parms",
TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
- else if (! flag_traditional)
+ else
warning ("%s defined inside parms",
TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
}
field widths. */
if (DECL_INITIAL (x))
{
- int max_width;
- if (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == c_bool_type_node)
- max_width = CHAR_TYPE_SIZE;
- else
- max_width = TYPE_PRECISION (TREE_TYPE (x));
+ int max_width
+ = (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == c_bool_type_node
+ ? CHAR_TYPE_SIZE : TYPE_PRECISION (TREE_TYPE (x)));
+
if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
error_with_decl (x, "negative width in bit-field `%s'");
else if (0 < compare_tree_int (DECL_INITIAL (x), max_width))
{
/* The test above has assured us that TREE_INT_CST_HIGH is 0. */
unsigned HOST_WIDE_INT width
- = TREE_INT_CST_LOW (DECL_INITIAL (x));
+ = tree_low_cst (DECL_INITIAL (x), 1);
if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
&& (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
DECL_BIT_FIELD (x) = 1;
SET_DECL_C_BIT_FIELD (x);
- if (width == 0)
+ if (width == 0
+ && ! (* targetm.ms_bitfield_layout_p) (t))
{
/* field size 0 => force desired amount of alignment. */
#ifdef EMPTY_FIELD_BOUNDARY
else if (! saw_named_field)
error_with_decl (x, "flexible array member in otherwise empty struct");
}
+
+ if (pedantic && TREE_CODE (t) == RECORD_TYPE
+ && flexible_array_type_p (TREE_TYPE (x)))
+ pedwarn_with_decl (x, "invalid use of structure with flexible array member");
+
if (DECL_NAME (x))
saw_named_field = 1;
}
/* If this structure or union completes the type of any previous
variable declaration, lay it out and output its rtl. */
- if (current_binding_level->n_incomplete != 0)
+ if (current_binding_level->incomplete_list != NULL_TREE)
{
- tree decl;
- for (decl = current_binding_level->names; decl; decl = TREE_CHAIN (decl))
- {
+ tree prev = NULL_TREE;
+
+ for (x = current_binding_level->incomplete_list; x; x = TREE_CHAIN (x))
+ {
+ tree decl = TREE_VALUE (x);
+
if (TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TYPE_MAIN_VARIANT (t)
&& TREE_CODE (decl) != TYPE_DECL)
{
layout_decl (decl, 0);
- /* This is a no-op in c-lang.c or something real in objc-actions.c. */
- maybe_objc_check_decl (decl);
+ /* This is a no-op in c-lang.c or something real in objc-act.c. */
+ if (flag_objc)
+ objc_check_decl (decl);
rest_of_decl_compilation (decl, NULL, toplevel, 0);
if (! toplevel)
expand_decl (decl);
- --current_binding_level->n_incomplete;
+ /* Unlink X from the incomplete list. */
+ if (prev)
+ TREE_CHAIN (prev) = TREE_CHAIN (x);
+ else
+ current_binding_level->incomplete_list = TREE_CHAIN (x);
}
else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
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);
+ if (flag_objc)
+ objc_check_decl (decl);
+ rest_of_decl_compilation (decl, NULL, toplevel, 0);
+ if (! toplevel)
+ expand_decl (decl);
+ }
+ /* Unlink X from the incomplete list. */
+ if (prev)
+ TREE_CHAIN (prev) = TREE_CHAIN (x);
+ else
+ current_binding_level->incomplete_list = TREE_CHAIN (x);
+ }
}
}
}
min_precision (maxnode, unsign));
if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
{
- tree narrowest = type_for_size (precision, unsign);
+ tree narrowest = c_common_type_for_size (precision, unsign);
if (narrowest == 0)
{
warning ("enumeration values exceed range of largest integer");
precision = TYPE_PRECISION (integer_type_node);
if (precision == TYPE_PRECISION (integer_type_node))
- enum_value_type = type_for_size (precision, 0);
+ enum_value_type = c_common_type_for_size (precision, 0);
else
enum_value_type = enumtype;
/* Now create a declaration for the enum value name. */
type = TREE_TYPE (value);
- type = type_for_size (MAX (TYPE_PRECISION (type),
- TYPE_PRECISION (integer_type_node)),
- ((flag_traditional
- || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))
- && TREE_UNSIGNED (type)));
+ type = c_common_type_for_size (MAX (TYPE_PRECISION (type),
+ TYPE_PRECISION (integer_type_node)),
+ (TYPE_PRECISION (type)
+ >= TYPE_PRECISION (integer_type_node)
+ && TREE_UNSIGNED (type)));
decl = build_decl (CONST_DECL, name, type);
DECL_INITIAL (decl) = convert (type, value);
current_function_returns_value = 0; /* Assume, until we see it does. */
current_function_returns_null = 0;
+ current_function_returns_abnormally = 0;
warn_about_return_type = 0;
current_extern_inline = 0;
- c_function_varargs = 0;
named_labels = 0;
shadowed_labels = 0;
decl_attributes (&decl1, attributes, 0);
+ /* If #pragma weak was used, mark the decl weak now. */
+ if (current_binding_level == global_binding_level)
+ maybe_apply_pragma_weak (decl1);
+
if (DECL_DECLARED_INLINE_P (decl1)
&& DECL_UNINLINABLE (decl1)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
/* Promote the value to int before returning it. */
if (c_promoting_integer_type_p (restype))
{
- /* It retains unsignedness if traditional
- or if not really getting wider. */
+ /* It retains unsignedness if not really getting wider. */
if (TREE_UNSIGNED (restype)
- && (flag_traditional
- || (TYPE_PRECISION (restype)
- == TYPE_PRECISION (integer_type_node))))
+ && (TYPE_PRECISION (restype)
+ == TYPE_PRECISION (integer_type_node)))
restype = unsigned_type_node;
else
restype = integer_type_node;
return 1;
}
-
-/* Record that this function is going to be a varargs function.
- This is called before store_parm_decls, which is too early
- to call mark_varargs directly. */
-
-void
-c_mark_varargs ()
-{
- c_function_varargs = 1;
-}
\f
/* Store the parameter declarations into the current function declaration.
This is called after parsing the parameter declarations, before
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;
- /* The function containing FNDECL, if any. */
- tree context = decl_function_context (fndecl);
+ int saved_warn_shadow = warn_shadow;
+
+ /* Don't re-emit shadow warnings. */
+ warn_shadow = 0;
if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST)
{
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)
{
"prototype declaration");
}
}
- /* If -traditional, allow `int' argument to match
- `unsigned' prototype. */
- else if (! (flag_traditional
- && TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == integer_type_node
- && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node))
+ else
{
error ("argument `%s' doesn't match prototype",
IDENTIFIER_POINTER (DECL_NAME (parm)));
not safe to try to expand expressions involving them. */
immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1;
+
+ warn_shadow = saved_warn_shadow;
}
\f
/* Finish up a function declaration and compile that function
This is called after parsing the body of the function definition.
- NESTED is nonzero if the function being finished is nested in another. */
+ NESTED is nonzero if the function being finished is nested in another.
+ CAN_DEFER_P is nonzero if the function may be deferred. */
void
-finish_function (nested)
+finish_function (nested, can_defer_p)
int nested;
+ int can_defer_p;
{
tree fndecl = current_function_decl;
-/* TREE_READONLY (fndecl) = 1;
- This caused &foo to be of type ptr-to-const-function
- which then got a warning when stored in a ptr-to-function variable. */
+#if 0
+ /* This caused &foo to be of type ptr-to-const-function which then
+ got a warning when stored in a ptr-to-function variable. */
+ TREE_READONLY (fndecl) = 1;
+#endif
poplevel (1, 0, 1);
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
- /* Obey `register' declarations if `setjmp' is called in this fn. */
- if (flag_traditional && current_function_calls_setjmp)
- {
- setjmp_protect (DECL_INITIAL (fndecl));
- setjmp_protect_args ();
- }
-
if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted)
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
/* Tie off the statement tree for this function. */
finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+
+ /* Complain if there's just no return statement. */
+ if (warn_return_type
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
+ && !current_function_returns_value && !current_function_returns_null
+ /* Don't complain if we abort. */
+ && !current_function_returns_abnormally
+ /* Don't warn for main(). */
+ && !MAIN_NAME_P (DECL_NAME (fndecl))
+ /* Or if they didn't actually specify a return type. */
+ && !C_FUNCTION_IMPLICIT_INT (fndecl)
+ /* Normally, with -Wreturn-type, flow will complain. Unless we're an
+ inline function, as we might never be compiled separately. */
+ && DECL_INLINE (fndecl))
+ warning ("no return statement in function returning non-void");
+
/* Clear out memory we no longer need. */
free_after_parsing (cfun);
/* Since we never call rest_of_compilation, we never clear
free_after_compilation (cfun);
cfun = NULL;
+ if (flag_unit_at_a_time && can_defer_p)
+ {
+ cgraph_finalize_function (fndecl, DECL_SAVED_TREE (fndecl));
+ current_function_decl = NULL;
+ return;
+ }
+
if (! nested)
{
- /* Generate RTL for the body of this function. */
- c_expand_body (fndecl, nested, 1);
+ /* Function is parsed.
+ Generate RTL for the body of this function or defer
+ it for later expansion. */
+ 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)
+ {
+ current_function_decl = NULL;
+ DECL_SAVED_TREE (fndecl) = NULL_TREE;
+ 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, 0);
+
+ 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);
+ current_function_decl = NULL;
+ return;
+ }
+
+ /* Then, inline any functions called in it. */
+ optimize_inline_calls (fndecl);
+ timevar_pop (TV_INTEGRATION);
+ }
+
+ c_expand_body (fndecl);
+
+ if (uninlinable)
+ {
+ /* Allow the body of the function to be garbage collected. */
+ DECL_SAVED_TREE (fndecl) = NULL_TREE;
+ }
+
/* 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. */
+ c_pop_function_context and then reset via pop_function_context. */
current_function_decl = NULL;
}
}
function was deferred, e.g. in duplicate_decls. */
if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl))
{
- c_expand_body (fndecl, 0, 0);
+ if (flag_inline_trees)
+ {
+ timevar_push (TV_INTEGRATION);
+ optimize_inline_calls (fndecl);
+ timevar_pop (TV_INTEGRATION);
+ }
+ c_expand_body (fndecl);
current_function_decl = NULL;
}
}
-/* Generate the RTL for the body of FNDECL. If NESTED_P is non-zero,
+/* Generate the RTL for the body of FNDECL. If NESTED_P is nonzero,
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)
+c_expand_body_1 (fndecl, nested_p)
tree fndecl;
- int nested_p, can_defer_p;
+ int nested_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)
/* 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));
+ lineno = DECL_SOURCE_LINE (fndecl);
/* This function is being processed in whole-function mode. */
cfun->x_whole_function_mode_p = 1;
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);
/* 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
if (nested_p)
ggc_pop_context ();
- /* With just -W, complain only if function returns both with
+ /* With just -Wextra, complain only if function returns both with
and without a value. */
if (extra_warnings
&& current_function_returns_value
/* 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.
+ For a nested function, this is done in c_pop_function_context.
If rest_of_compilation set this to 0, leave it 0. */
if (DECL_INITIAL (fndecl) != 0)
DECL_INITIAL (fndecl) = error_mark_node;
pop_function_context ();
timevar_pop (TV_EXPAND);
}
+
+/* Like c_expand_body_1 but only for unnested functions. */
+
+void
+c_expand_body (fndecl)
+ tree fndecl;
+{
+ c_expand_body_1 (fndecl, 0);
+}
\f
/* Check the declarations given in a for-loop for satisfying the C99
constraints. */
that keep track of the progress of compilation of the current function.
Used for nested functions. */
-struct c_language_function
+struct language_function GTY(())
{
- struct language_function base;
+ struct c_language_function base;
tree named_labels;
tree shadowed_labels;
int returns_value;
int returns_null;
+ int returns_abnormally;
int warn_about_return_type;
int extern_inline;
struct binding_level *binding_level;
used during compilation of a C function. */
void
-push_c_function_context (f)
+c_push_function_context (f)
struct function *f;
{
- struct c_language_function *p;
- p = ((struct c_language_function *)
- xmalloc (sizeof (struct c_language_function)));
- f->language = (struct language_function *) p;
+ struct language_function *p;
+ p = ((struct language_function *)
+ ggc_alloc (sizeof (struct language_function)));
+ f->language = p;
p->base.x_stmt_tree = c_stmt_tree;
p->base.x_scope_stmt_stack = c_scope_stmt_stack;
p->shadowed_labels = shadowed_labels;
p->returns_value = current_function_returns_value;
p->returns_null = current_function_returns_null;
+ p->returns_abnormally = current_function_returns_abnormally;
p->warn_about_return_type = warn_about_return_type;
p->extern_inline = current_extern_inline;
p->binding_level = current_binding_level;
/* Restore the variables used during compilation of a C function. */
void
-pop_c_function_context (f)
+c_pop_function_context (f)
struct function *f;
{
- struct c_language_function *p
- = (struct c_language_function *) f->language;
+ struct language_function *p = f->language;
tree link;
/* Bring back all the labels that were shadowed. */
shadowed_labels = p->shadowed_labels;
current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null;
+ current_function_returns_abnormally = p->returns_abnormally;
warn_about_return_type = p->warn_about_return_type;
current_extern_inline = p->extern_inline;
current_binding_level = p->binding_level;
- free (p);
- f->language = 0;
+ f->language = NULL;
}
-/* Mark the language specific parts of F for GC. */
+/* Copy the DECL_LANG_SPECIFIC data associated with DECL. */
void
-mark_c_function_context (f)
- struct function *f;
-{
- struct c_language_function *p
- = (struct c_language_function *) f->language;
-
- if (p == 0)
- return;
-
- mark_c_language_function (&p->base);
- ggc_mark_tree (p->shadowed_labels);
- ggc_mark_tree (p->named_labels);
- mark_binding_level (&p->binding_level);
-}
-
-/* Copy the DECL_LANG_SPECIFIC data associated with NODE. */
-
-void
-copy_lang_decl (decl)
+c_dup_lang_specific_decl (decl)
tree decl;
{
struct lang_decl *ld;
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,
+/* Returns nonzero if the current statement is a full expression,
i.e. temporaries created during that statement should be destroyed
at the end of the statement. */
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);
+ c_expand_body_1 (decl, 1);
}
/* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since
tree t = build_tree_list (NULL_TREE, void_type_node);
return t;
}
+
+/* Return something to represent absolute declarators containing a *.
+ TARGET is the absolute declarator that the * contains.
+ TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
+ to apply to the pointer type, represented as identifiers, possible mixed
+ with attributes.
+
+ We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST,
+ if attributes are present) and whose type is the modifier list. */
+
+tree
+make_pointer_declarator (type_quals_attrs, target)
+ tree type_quals_attrs, target;
+{
+ tree quals, attrs;
+ tree itarget = target;
+ split_specs_attrs (type_quals_attrs, &quals, &attrs);
+ if (attrs != NULL_TREE)
+ itarget = tree_cons (attrs, target, NULL_TREE);
+ return build1 (INDIRECT_REF, quals, itarget);
+}
+
+#include "gt-c-decl.h"