/* 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 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,
#include "system.h"
#include "intl.h"
#include "tree.h"
+#include "tree-inline.h"
#include "rtl.h"
#include "flags.h"
#include "function.h"
#include "ggc.h"
#include "tm_p.h"
#include "cpplib.h"
+#include "target.h"
+#include "debug.h"
+#include "timevar.h"
+#include "c-common.h"
+#include "c-pragma.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
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. */
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));
+static void c_expand_body PARAMS ((tree, int, int));
+static void warn_if_shadowing PARAMS ((tree, tree));
\f
/* 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;
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;
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 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
#endif
int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
+/* 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. */
char **argv;
{
int strings_processed;
- const char *option_value = NULL;
char *p = argv[0];
- strings_processed = cpp_handle_option (parse_in, argc, argv);
+ static const struct {
+ /* The name of the option. */
+ const char *option;
+ /* If non-NULL, a flag variable to set to 0 or 1. If NULL,
+ this means that cpp handles this option. */
+ int *flag;
+ } warn_options[] = {
+ /* This list is in alphabetical order. Keep it like that. */
+ { "bad-function-cast", &warn_bad_function_cast },
+ { "cast-qual", &warn_cast_qual },
+ { "char-subscripts", &warn_char_subscripts },
+ { "comment", NULL },
+ { "comments", NULL },
+ { "conversion", &warn_conversion },
+ { "div-by-zero", &warn_div_by_zero },
+ { "float-equal", &warn_float_equal },
+ { "format-extra-args", &warn_format_extra_args },
+ { "format-nonliteral", &warn_format_nonliteral },
+ { "format-security", &warn_format_security },
+ { "format-y2k", &warn_format_y2k },
+ { "implicit-function-declaration", &mesg_implicit_function_declaration },
+ { "implicit-int", &warn_implicit_int },
+ { "import", NULL },
+ { "long-long", &warn_long_long },
+ { "main", &warn_main },
+ { "missing-braces", &warn_missing_braces },
+ { "missing-declarations", &warn_missing_declarations },
+ { "missing-format-attribute", &warn_missing_format_attribute },
+ { "missing-prototypes", &warn_missing_prototypes },
+ { "multichar", &warn_multichar },
+ { "nested-externs", &warn_nested_externs },
+ { "parentheses", &warn_parentheses },
+ { "pointer-arith", &warn_pointer_arith },
+ { "redundant-decls", &warn_redundant_decls },
+ { "return-type", &warn_return_type },
+ { "sequence-point", &warn_sequence_point },
+ { "sign-compare", &warn_sign_compare },
+ { "strict-prototypes", &warn_strict_prototypes },
+ { "traditional", &warn_traditional },
+ { "trigraphs", NULL },
+ { "undef", NULL },
+ { "write-strings", &flag_const_strings }
+ };
- if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
- {
- flag_traditional = 1;
- flag_writable_strings = 1;
- }
- else if (!strcmp (p, "-fallow-single-precision"))
- flag_allow_single_precision = 1;
- else if (!strcmp (p, "-fhosted") || !strcmp (p, "-fno-freestanding"))
+ strings_processed = cpp_handle_option (parse_in, argc, argv, 0);
+
+ if (!strcmp (p, "-fhosted") || !strcmp (p, "-fno-freestanding"))
{
flag_hosted = 1;
flag_no_builtin = 0;
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
-std=gnu89 default, iso9899:1990 + 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;
|| !strcmp (argstart, "c9x")
|| !strcmp (argstart, "c99"))
{
- flag_traditional = 0;
flag_writable_strings = 0;
flag_no_asm = 1;
flag_no_nonansi_builtin = 1;
}
else if (!strcmp (argstart, "gnu89"))
{
- flag_traditional = 0;
flag_writable_strings = 0;
flag_no_asm = 0;
flag_no_nonansi_builtin = 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_isoc99 = 1;
flag_isoc94 = 1;
}
+ else if (!strcmp (argstart, "c++98"))
+ ; /* Handled by cpplib. */
else
error ("unknown C standard `%s'", argstart);
}
flag_no_builtin = 0;
else if (!strcmp (p, "-fno-builtin"))
flag_no_builtin = 1;
- else if ((option_value
- = skip_leading_substring (p, "-fdump-translation-unit-")))
- {
- if (p[22] == '\0')
- error ("no file specified with -fdump-translation-unit");
- else
- flag_dump_translation_unit = option_value;
- }
+ 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 (!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, "-Wimplicit"))
{
warn_implicit_int = 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, "-Wunknown-pragmas"))
/* Set to greater than 1, so that even unknown pragmas in system
headers will be warned about. */
/* Only warn about unknown pragmas that are not in system headers. */
warn_unknown_pragmas = 1;
}
+ else if (!strcmp (p, "-E"))
+ flag_preprocess_only = 1;
else
- return strings_processed;
+ {
+ size_t i;
+ for (i = 0; i < sizeof (warn_options) / sizeof (warn_options[0]); i++)
+ if (strncmp (p, "-W", 2) == 0
+ && warn_options[i].flag
+ && (strcmp (p+2, warn_options[i].option) == 0
+ || (strncmp (p+2, "no-", 3) == 0
+ && strcmp (p+5, warn_options[i].option) == 0)))
+ {
+ *(warn_options[i].flag) = strncmp (p+2, "no-", 3) != 0;
+ return 1;
+ }
+ return strings_processed;
+ }
return 1;
}
-/* Hooks for print_node. */
-
void
-print_lang_decl (file, node, indent)
- FILE *file ATTRIBUTE_UNUSED;
- tree node ATTRIBUTE_UNUSED;
- int indent ATTRIBUTE_UNUSED;
-{
-}
-
-void
-print_lang_type (file, node, indent)
- FILE *file ATTRIBUTE_UNUSED;
- tree node ATTRIBUTE_UNUSED;
- int indent ATTRIBUTE_UNUSED;
-{
-}
-
-void
-print_lang_identifier (file, node, indent)
+c_print_identifier (file, node, indent)
FILE *file;
tree node;
int 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)
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. */
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;
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)
{
/* 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;
return block;
}
-/* Delete the node BLOCK from the current binding level.
- This is used for the block inside a stmt expr ({...})
- so that the block can be reinserted where appropriate. */
-
-void
-delete_block (block)
- tree block;
-{
- tree t;
- if (current_binding_level->blocks == block)
- current_binding_level->blocks = TREE_CHAIN (block);
- for (t = current_binding_level->blocks; t;)
- {
- if (TREE_CHAIN (t) == block)
- TREE_CHAIN (t) = TREE_CHAIN (block);
- else
- t = TREE_CHAIN (t);
- }
- TREE_CHAIN (block) = NULL;
- /* Clear TREE_USED which is always set by poplevel.
- The flag is set again if insert_block is called. */
- TREE_USED (block) = 0;
-}
-
/* Insert BLOCK at the end of the list of subblocks of the
current binding level. This is used when a BIND_EXPR is expanded,
to handle the BLOCK node inside the BIND_EXPR. */
void
set_block (block)
- register tree block;
+ tree block;
{
current_binding_level->this_block = block;
current_binding_level->names = chainon (current_binding_level->names,
void
push_label_level ()
{
- register struct binding_level *newlevel;
+ struct binding_level *newlevel;
/* Reuse or create a struct for this binding 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.
pushtag (name, type)
tree name, type;
{
- register struct binding_level *b;
+ struct binding_level *b;
/* Find the proper binding level for this type tag. */
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));
int errmsg = 0;
if (DECL_P (olddecl))
- DECL_MACHINE_ATTRIBUTES (newdecl)
- = merge_machine_decl_attributes (olddecl, newdecl);
+ {
+ 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)
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))
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)
tree_cons (NULL_TREE,
TREE_VALUE (TYPE_ARG_TYPES (newtype)),
TREE_CHAIN (TYPE_ARG_TYPES (oldtype))));
+ trytype = build_type_attribute_variant (trytype,
+ TYPE_ATTRIBUTES (oldtype));
types_match = comptypes (newtype, trytype);
if (types_match)
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. */
&& 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 (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;
}
}
&& 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_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),
}
/* 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",
/* 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");
{
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,
been written out yet. */
if (new_is_definition && DECL_INITIAL (olddecl) && TREE_USED (olddecl))
{
- note_outlining_of_inline_function (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_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
- DECL_INLINE (olddecl) = 1;
+ if (DECL_DECLARED_INLINE_P (newdecl)
+ || DECL_DECLARED_INLINE_P (olddecl))
+ DECL_DECLARED_INLINE_P (newdecl) = 1;
- DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+ DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
+ = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
}
if (DECL_BUILT_IN (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);
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_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)
/* 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);
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
/* 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).
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.
&& 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)
{
- const 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)
+ if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x))
{
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)
error_with_decl (x, "`%s' used prior to declaration");
}
- if (t != 0)
- {
- file = DECL_SOURCE_FILE (t);
- line = DECL_SOURCE_LINE (t);
- }
-
/* If this decl is `static' and an implicit decl was seen previously,
- warn. But don't complain if -traditional,
- since traditional compilers don't complain. */
- if (! flag_traditional && TREE_PUBLIC (name)
+ warn. */
+ if (TREE_PUBLIC (name)
/* Don't test for DECL_EXTERNAL, because grokdeclarator
sets this for all functions. */
&& ! TREE_PUBLIC (x)
}
/* 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)
&& oldglobal != 0
&& TREE_CODE (x) == FUNCTION_DECL
&& TREE_CODE (oldglobal) == FUNCTION_DECL
- && DECL_EXTERNAL (x) && ! DECL_INLINE (x))
+ && DECL_EXTERNAL (x)
+ && ! DECL_DECLARED_INLINE_P (x))
{
/* We have one. Their types must agree. */
if (! comptypes (TREE_TYPE (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));
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. */
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->n_incomplete;
+ }
}
/* Put decls on list in reverse order.
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);
implicitly_declare (functionid)
tree functionid;
{
- register tree decl;
+ tree decl;
int traditional_warning = 0;
/* Only one "implicit declaration" warning per identifier. */
int implicit_warning;
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);
- rest_of_decl_compilation (decl, NULL_PTR, 0, 0);
+ rest_of_decl_compilation (decl, NULL, 0, 0);
if (implicit_warning)
implicit_decl_warning (functionid);
gen_aux_info_record (decl, 0, 1, 0);
+ /* Possibly apply some default attributes to this implicit declaration. */
+ decl_attributes (&decl, NULL_TREE, 0);
+
return decl;
}
{
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;
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;
}
lookup_label (id)
tree id;
{
- register tree decl = IDENTIFIER_LABEL_VALUE (id);
+ tree decl = IDENTIFIER_LABEL_VALUE (id);
if (current_function_decl == 0)
{
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 */
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)
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)
lookup_name (name)
tree name;
{
- register tree val;
+ tree val;
if (current_binding_level != global_binding_level
&& IDENTIFIER_LOCAL_VALUE (name))
lookup_name_current_level (name)
tree name;
{
- register tree t;
+ tree t;
if (current_binding_level == global_binding_level)
return IDENTIFIER_GLOBAL_VALUE (name);
Make definitions for built-in primitive functions. */
void
-init_decl_processing ()
+c_init_decl_processing ()
{
- register tree endlink;
+ 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;
= build_function_type (ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node, endlink));
- /* Types which are common to the fortran compiler and libf2c. When
- changing these, you also need to be concerned with f/com.h. */
-
- if (TYPE_PRECISION (float_type_node)
- == TYPE_PRECISION (long_integer_type_node))
- {
- g77_integer_type_node = long_integer_type_node;
- g77_uinteger_type_node = long_unsigned_type_node;
- }
- else if (TYPE_PRECISION (float_type_node)
- == TYPE_PRECISION (integer_type_node))
- {
- g77_integer_type_node = integer_type_node;
- g77_uinteger_type_node = unsigned_type_node;
- }
- else
- g77_integer_type_node = g77_uinteger_type_node = NULL_TREE;
-
- if (g77_integer_type_node != NULL_TREE)
- {
- pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_integer"),
- g77_integer_type_node));
- pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_uinteger"),
- g77_uinteger_type_node));
- }
-
- if (TYPE_PRECISION (float_type_node) * 2
- == TYPE_PRECISION (long_integer_type_node))
- {
- g77_longint_type_node = long_integer_type_node;
- g77_ulongint_type_node = long_unsigned_type_node;
- }
- else if (TYPE_PRECISION (float_type_node) * 2
- == TYPE_PRECISION (long_long_integer_type_node))
- {
- g77_longint_type_node = long_long_integer_type_node;
- g77_ulongint_type_node = long_long_unsigned_type_node;
- }
- else
- g77_longint_type_node = g77_ulongint_type_node = NULL_TREE;
-
- if (g77_longint_type_node != NULL_TREE)
- {
- pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_longint"),
- g77_longint_type_node));
- pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_ulongint"),
- g77_ulongint_type_node));
- }
-
- builtin_function ("__builtin_aggregate_incoming_address",
- build_function_type (ptr_type_node, NULL_TREE),
- BUILT_IN_AGGREGATE_INCOMING_ADDRESS,
- BUILT_IN_NORMAL, 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, BUILT_IN_NORMAL, NULL_PTR);
- builtin_function ("__builtin_dwarf_cfa", ptr_ftype_void,
- BUILT_IN_DWARF_CFA, BUILT_IN_NORMAL, NULL_PTR);
- builtin_function ("__builtin_dwarf_fp_regnum",
- build_function_type (unsigned_type_node, endlink),
- BUILT_IN_DWARF_FP_REGNUM, BUILT_IN_NORMAL, NULL_PTR);
- builtin_function ("__builtin_init_dwarf_reg_size_table", void_ftype_ptr,
- BUILT_IN_INIT_DWARF_REG_SIZES, BUILT_IN_NORMAL, NULL_PTR);
- builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
- BUILT_IN_FROB_RETURN_ADDR, BUILT_IN_NORMAL, NULL_PTR);
- builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
- BUILT_IN_EXTRACT_RETURN_ADDR, BUILT_IN_NORMAL, NULL_PTR);
- builtin_function
- ("__builtin_eh_return",
- build_function_type (void_type_node,
- tree_cons (NULL_TREE,
- type_for_mode (ptr_mode, 0),
- tree_cons (NULL_TREE,
- ptr_type_node,
- endlink))),
- BUILT_IN_EH_RETURN, BUILT_IN_NORMAL, NULL_PTR);
-
pedantic_lvalues = pedantic;
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
- start_identifier_warnings ();
-
- /* Prepare to check format strings against argument lists. */
- init_function_format_info ();
-
- incomplete_decl_finalize_hook = finish_incomplete_decl;
-
/* Record our roots. */
ggc_add_tree_root (c_global_trees, CTI_MAX);
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. */
+ /* We don't push the decl, so have to set its context here. */
DECL_CONTEXT (decl) = current_function_decl;
TREE_STATIC (decl) = 1;
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_PTR);
+ make_decl_rtl (decl, NULL);
pushdecl (decl);
DECL_BUILT_IN_CLASS (decl) = class;
DECL_FUNCTION_CODE (decl) = function_code;
+ /* The return builtins leave the current function. */
+ if (function_code == BUILT_IN_RETURN || function_code == BUILT_IN_EH_RETURN)
+ TREE_THIS_VOLATILE (decl) = 1;
+
/* 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
+c_insert_default_attributes (decl)
+ tree decl;
+{
+ if (!TREE_PUBLIC (decl))
+ return;
+ c_common_insert_default_attributes (decl);
+}
\f
/* 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
no pedwarn. */
{
int found_tag = 0;
- register tree link;
+ tree link;
tree specs, attrs;
pending_invalid_xref = 0;
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++;
}
}
\f
+/* 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;
+}
+\f
/* 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);
+
+ /* Apply attributes. */
+ decl_attributes (&typename, attrs, 0);
+
+ return typename;
}
/* Return a PARM_DECL node for a given pair of specs and declarator. */
grokfield and not through here. */
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;
+ 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)))
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))
+ if (!initialized && (! 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 #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)
+ && 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. */
tree decl, init;
tree asmspec_tree;
{
- register tree type = TREE_TYPE (decl);
+ tree type = TREE_TYPE (decl);
int was_incomplete = (DECL_SIZE (decl) == 0);
const char *asmspec = 0;
- /* If a name was specified, get the string. */
+ /* 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);
}
else
{
+ /* This is a local variable. If there is an ASMSPEC, the
+ user has requested that we handle it specially. */
if (asmspec)
{
- SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
- DECL_C_HARD_REGISTER (decl) = 1;
+ /* 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));
}
- add_decl_stmt (decl);
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ add_decl_stmt (decl);
}
if (DECL_CONTEXT (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, DECL_CONTEXT (decl) == 0, 0);
+ rest_of_decl_compilation (decl, NULL, DECL_CONTEXT (decl) == 0, 0);
}
/* At the end of a declaration, throw away any variable type sizes
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,
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)));
+ decl_attributes (&decl, TREE_VALUE (parm), 0);
#if 0
if (DECL_NAME (decl))
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");
+ "ISO C forbids parameter `%s' shadowing typedef");
}
#endif
current_binding_level->parm_order = NULL_TREE;
}
\f
+/* 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;
+}
+\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). */
tree initial_value;
int do_default;
{
- register tree maxindex = NULL_TREE;
+ tree maxindex = NULL_TREE;
int value = 0;
if (initial_value)
enum tree_code innermost_code = ERROR_MARK;
int bitfield = 0;
int size_varies = 0;
- tree decl_machine_attr = NULL_TREE;
+ tree decl_attr = NULL_TREE;
+ tree array_ptr_quals = NULL_TREE;
+ int array_parm_static = 0;
+ tree returned_attrs = NULL_TREE;
if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
/* 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)
decl = TREE_OPERAND (decl, 0);
break;
+ case TREE_LIST:
+ decl = TREE_VALUE (decl);
+ break;
+
case IDENTIFIER_NODE:
name = IDENTIFIER_POINTER (decl);
decl = 0;
for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
{
- 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;
/* 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)
/* 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;
}
/* 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).
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)
+ {
+ /* 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;
+ else if (TREE_CODE (inner_decl) == CALL_EXPR)
+ attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
+ else if (TREE_CODE (inner_decl) == ARRAY_REF)
+ attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
+ returned_attrs = decl_attributes (&type,
+ chainon (returned_attrs, attrs),
+ attr_flags);
+ }
+ else if (TREE_CODE (declarator) == ARRAY_REF)
{
- register tree itype = NULL_TREE;
- register tree size = TREE_OPERAND (declarator, 1);
+ 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);
declarator = TREE_OPERAND (declarator, 0);
/* 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;
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
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)
{
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. */
the FUNCTION_TYPE node itself. */
{
- register tree link;
+ tree link;
for (link = last_function_parm_tags;
link;
if (TREE_TYPE (declarator))
{
- register tree typemodlist;
+ tree typemodlist;
int erred = 0;
constp = 0;
&& TREE_OVERFLOW (TYPE_SIZE (type)))
{
error ("size of array `%s' is too large", name);
- /* If we proceed with the array type as it is, we'll eventully
+ /* If we proceed with the array type as it is, we'll eventually
crash in tree_low_cst(). */
type = error_mark_node;
}
if ((specbits & (1 << (int) RID_SIGNED))
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
+ decl_attributes (&decl, returned_attrs, 0);
return decl;
}
pedwarn ("ISO C forbids const or volatile function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
+ decl_attributes (&type, returned_attrs, 0);
return type;
}
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 type_as_written;
tree promoted_type;
/* A parameter declared as an array of T is really a pointer to T.
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)
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)
pedwarn ("invalid storage class for function `%s'", name);
decl = build_decl (FUNCTION_DECL, declarator, type);
- decl = build_decl_attribute_variant (decl, decl_machine_attr);
+ decl = build_decl_attribute_variant (decl, decl_attr);
+
+ DECL_LANG_SPECIFIC (decl) = (struct lang_decl *)
+ ggc_alloc_cleared (sizeof (struct lang_decl));
if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ISO C forbids qualified function types");
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 (inlinep)
+ if (MAIN_NAME_P (declarator))
{
- if (MAIN_NAME_P (declarator))
+ 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
type_quals = TYPE_UNQUALIFIED;
#endif
}
-
+ else if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
+
decl = build_decl (VAR_DECL, declarator, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
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);
return decl;
}
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 type = TREE_TYPE (decl);
DECL_ARG_TYPE (decl) = type;
if (PROMOTE_PROTOTYPES
- && (TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
+ && INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (decl) = integer_type_node;
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
{
- /* For translation these need to be seperate warnings */
+ /* For translation these need to be separate warnings */
if (code == RECORD_TYPE)
warning ("anonymous struct declared inside parameter list");
else if (code == UNION_TYPE)
}
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;
}
}
/* 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;
/* If no such tag is yet defined, create a forward-reference node
/* If there is already a tag defined at this binding level
(as a forward reference), just return it. */
- register tree ref = 0;
+ tree ref = 0;
if (name != 0)
ref = lookup_tag (code, name, current_binding_level, 1);
C_TYPE_BEING_DEFINED (ref) = 1;
TYPE_PACKED (ref) = flag_pack_struct;
if (TYPE_FIELDS (ref))
- error ("redefinition of `%s %s'",
- code == UNION_TYPE ? "union" : "struct",
- 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;
}
{
tree value;
+ 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);
finish_decl (value, NULL_TREE, NULL_TREE);
tree fieldlist;
tree attributes;
{
- register tree x;
+ tree x;
int toplevel = global_binding_level == current_binding_level;
int saw_named_field;
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)
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
x = TREE_CHAIN (x);
else
{
- register tree y = fieldlist;
+ tree y = fieldlist;
while (1)
{
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 (!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);
+ 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;
+ }
}
}
}
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
tree values;
tree attributes;
{
- register tree pair, tem;
+ 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. */
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;
build_enumerator (name, value)
tree name, value;
{
- register tree decl, type;
+ tree decl, type;
/* Validate and default VALUE. */
/* Now create a declaration for the enum value name. */
type = TREE_TYPE (value);
- type = type_for_size (MAX (TYPE_PRECISION (type),
- TYPE_PRECISION (integer_type_node)),
- ((flag_traditional
- || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))
- && TREE_UNSIGNED (type)));
+ 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);
\f
/* 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.
yyparse to report a parse error. */
int
-start_function (declspecs, declarator, prefix_attributes, attributes)
- tree declarator, declspecs, prefix_attributes, attributes;
+start_function (declspecs, declarator, attributes)
+ tree declarator, declspecs, attributes;
{
tree decl1, old_decl;
tree restype;
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;
return 0;
}
- decl_attributes (decl1, prefix_attributes, attributes);
+ 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)))
+ warning_with_decl (decl1,
+ "inline function `%s' given attribute noinline");
announce_function (decl1);
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;
/* 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;
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). */
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.
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;
for (parm = specparms; parm; parm = TREE_CHAIN (parm))
{
- register tree tail, found = NULL;
+ tree tail, found = NULL;
if (TREE_VALUE (parm) == 0)
{
}
/* If declaration already marked, we have a duplicate name.
- Complain, and don't use this decl twice. */
+ Complain, and don't use this decl twice. */
if (found && DECL_WEAK (found))
{
error_with_decl (found, "multiple parameters named `%s'");
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)
{
parm = specparms;
DECL_ARGUMENTS (fndecl) = 0;
{
- register tree last;
+ tree last;
for (last = 0; parm; parm = TREE_CHAIN (parm))
if (TREE_PURPOSE (parm))
{
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))
"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)))
DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
if (PROMOTE_PROTOTYPES
- && (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
- || TREE_CODE (TREE_TYPE (parm)) == ENUMERAL_TYPE)
+ && INTEGRAL_TYPE_P (TREE_TYPE (parm))
&& TYPE_PRECISION (TREE_TYPE (parm))
< TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (parm) = integer_type_node;
"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)));
gen_aux_info_record (fndecl, 1, 0, prototype);
/* Initialize the RTL code for the function. */
-
init_function_start (fndecl, input_filename, lineno);
/* Begin the statement tree for this function. */
- DECL_LANG_SPECIFIC (current_function_decl)
- =((struct lang_decl *) ggc_alloc (sizeof (struct lang_decl)));
begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
+ /* 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)
+ {
+ 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;
+ }
+
/* This function is being processed in whole-function mode. */
cfun->x_whole_function_mode_p = 1;
not safe to try to expand expressions involving them. */
immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1;
-}
-\f
-/* 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_WEAK (parm) = 0;
-
- for (parm = specparms; parm; parm = TREE_CHAIN (parm))
- {
- register tree tail, found = NULL;
-
- /* See if any of the parmdecls specifies this parm by name. */
- for (tail = parmdecls; tail; tail = TREE_CHAIN (tail))
- if (DECL_NAME (tail) == TREE_VALUE (parm))
- {
- found = tail;
- break;
- }
-
- /* If declaration already marked, we have a duplicate name.
- Complain, and don't use this decl twice. */
- if (found && DECL_WEAK (found))
- {
- error_with_decl (found, "multiple parameters named `%s'");
- found = 0;
- }
-
- /* If the declaration says "void", complain and ignore it. */
- if (found && VOID_TYPE_P (TREE_TYPE (found)))
- {
- error_with_decl (found, "parameter `%s' declared void");
- TREE_TYPE (found) = integer_type_node;
- DECL_ARG_TYPE (found) = integer_type_node;
- layout_decl (found, 0);
- }
-
- /* 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". */
- DECL_WEAK (found) = 1;
- }
-
- /* 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 (!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
- = 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 = tree_cons (NULL_TREE, TREE_TYPE (parm), types);
- }
- }
-
- if (void_at_end)
- return tree_cons (parmdecls, nonparms,
- nreverse (tree_cons (NULL_TREE, void_type_node, types)));
-
- return tree_cons (parmdecls, nonparms, nreverse (types));
+ 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;
{
- 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
- 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
if (! nested)
{
/* Generate RTL for the body of this function. */
- c_expand_body (fndecl, nested);
+ c_expand_body (fndecl, nested, can_defer_p);
+
/* 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. */
}
}
+/* 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. */
+ 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)
+c_expand_body (fndecl, nested_p, can_defer_p)
tree fndecl;
- int nested_p;
+ 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;
- /* Squirrel away our current state. */
+ 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)
- push_function_context ();
+ {
+ /* 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. */
/* Generate the RTL for this function. */
expand_stmt (DECL_SAVED_TREE (fndecl));
- /* Allow the body of the function to be garbage collected. */
- DECL_SAVED_TREE (fndecl) = NULL_TREE;
+ 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 in start_function.
+ /* 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. */
}
}
- if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested_p)
+ 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
if (DECL_STATIC_CONSTRUCTOR (fndecl))
{
-#ifndef ASM_OUTPUT_CONSTRUCTOR
- if (! flag_gnu_linker)
- static_ctors = 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_ASSEMBLER_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 = 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_ASSEMBLER_NAME (fndecl)));
+ static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
}
if (nested_p)
- {
- /* Return to the enclosing function. */
- pop_function_context ();
- /* If the nested function was inline, write it out if that is
- necessary. */
- if (!TREE_ASM_WRITTEN (fndecl) && TREE_ADDRESSABLE (fndecl))
- {
- push_function_context ();
- output_inline_function (fndecl);
- pop_function_context ();
- }
- }
-
+ /* Return to the enclosing function. */
+ pop_function_context ();
+ timevar_pop (TV_EXPAND);
}
\f
/* Check the declarations given in a for-loop for satisfying the C99
for (t = gettags (); t; t = TREE_CHAIN (t))
{
if (TREE_PURPOSE (t) != 0)
- error ("`%s %s' declared in `for' loop initial declaration",
- (TREE_CODE (TREE_VALUE (t)) == RECORD_TYPE ? "struct"
- : TREE_CODE (TREE_VALUE (t)) == UNION_TYPE ? "union"
- : "enum"),
- IDENTIFIER_POINTER (TREE_PURPOSE (t)));
+ {
+ 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))
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;
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;
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;
mark_binding_level (&p->binding_level);
}
-/* Copy the DECL_LANG_SEPECIFIC data associated with NODE. */
+/* Copy the DECL_LANG_SPECIFIC data associated with DECL. */
void
-copy_lang_decl (decl)
+c_dup_lang_specific_decl (decl)
tree decl;
{
struct lang_decl *ld;
/* Mark the language specific bits in T for GC. */
void
-lang_mark_tree (t)
+c_mark_tree (t)
tree t;
{
if (TREE_CODE (t) == IDENTIFIER_NODE)
{
ggc_mark (DECL_LANG_SPECIFIC (t));
c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base);
+ ggc_mark_tree (DECL_LANG_SPECIFIC (t)->pending_sizes);
}
}
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_CONTEXT (decl) == current_function_decl
&& DECL_SAVED_TREE (decl))
- c_expand_body (decl, /*nested_p=*/1);
+ c_expand_body (decl, /*nested_p=*/1, /*can_defer_p=*/0);
}
/* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since