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,
and structure, union, array and enum types when they are declared. */
#include "defaults.h"
#include "ggc.h"
#include "tm_p.h"
-
-#if USE_CPPLIB
#include "cpplib.h"
-extern cpp_reader parse_in;
-#endif
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
#ifndef WCHAR_TYPE
#define WCHAR_TYPE "int"
#endif
-\f
-/* Do GC. */
-int ggc_p = 1;
+#ifndef WINT_TYPE
+#define WINT_TYPE "unsigned int"
+#endif
+
+#ifndef INTMAX_TYPE
+#define INTMAX_TYPE ((INT_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
+ ? "int" \
+ : ((LONG_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
+ ? "long int" \
+ : "long long int"))
+#endif
+
+#ifndef UINTMAX_TYPE
+#define UINTMAX_TYPE ((INT_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
+ ? "unsigned int" \
+ : ((LONG_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
+ ? "long unsigned int" \
+ : "long long unsigned int"))
+#endif
+\f
/* Nonzero if we have seen an invalid cross reference
to a struct, union, or enum, but not yet printed the message. */
static const char *current_function_prototype_file;
static int current_function_prototype_line;
+/* The current statement tree. */
+
+static struct stmt_tree_s c_stmt_tree;
+
+/* The current scope statement stack. */
+
+static tree c_scope_stmt_stack;
+
+/* Nonzero if __FUNCTION__ and its ilk have been declared in this
+ function. */
+
+static int c_function_name_declared_p;
+
/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
that have names. Here so we can clear out their names' definitions
at the end of the function. */
/* Nonzero means make a BLOCK if this level has any subblocks. */
char keep_if_subblocks;
- /* Number of decls in `names' that have incomplete
+ /* Number of decls in `names' that have incomplete
structure or union types. */
int n_incomplete;
};
#define NULL_BINDING_LEVEL (struct binding_level *) NULL
-
+
/* The binding level currently in effect. */
static struct binding_level *current_binding_level;
if it has subblocks. */
static int keep_next_if_subblocks;
-
+
/* The chain of outer levels of label scopes.
This uses the same data structure used for binding levels,
but it works differently: each link in the chain records
static tree grokparms PARAMS ((tree, int));
static void layout_array_type PARAMS ((tree));
static tree c_make_fname_decl PARAMS ((tree, const char *, int));
+static void c_expand_body PARAMS ((tree, int));
\f
/* C-specific option variables. */
int flag_no_asm;
-/* Nonzero means don't recognize any builtin functions. */
-
-int flag_no_builtin;
-
-/* Nonzero means don't recognize the non-ANSI builtin functions.
- -ansi sets this. */
-
-int flag_no_nonansi_builtin;
-
/* Nonzero means do some things the same way PCC does. */
int flag_traditional;
-/* Nonzero means use the ISO C99 dialect of C. */
+/* Nonzero means enable C89 Amendment 1 features. */
-int flag_isoc99 = 0;
+int flag_isoc94 = 0;
-/* Nonzero means accept digraphs. */
+/* Nonzero means use the ISO C99 dialect of C. */
-int flag_digraphs = 1;
+int flag_isoc99 = 0;
/* Nonzero means that we have builtin functions, and main is an int */
int flag_hosted = 1;
+/* Nonzero means add default format_arg attributes for functions not
+ in ISO C. */
+
+int flag_noniso_default_format_attributes = 1;
+
/* Nonzero means to allow single precision math even if we're generally
being traditional. */
int flag_allow_single_precision = 0;
int flag_signed_bitfields = 1;
int explicit_flag_signed_bitfields = 0;
-/* Nonzero means warn about use of implicit int. */
+/* Nonzero means warn about use of implicit int. */
int warn_implicit_int;
int warn_long_long = 1;
/* Nonzero means message about use of implicit function declarations;
- 1 means warning; 2 means error. */
+ 1 means warning; 2 means error. */
-int mesg_implicit_function_declaration;
+int mesg_implicit_function_declaration = -1;
/* Nonzero means give string constants the type `const char *'
to get extra warnings from them. These warnings will be too numerous
int warn_bad_function_cast;
-/* Warn about functions which might be candidates for attribute noreturn. */
+/* Warn about functions which might be candidates for format attributes. */
-int warn_missing_noreturn;
+int warn_missing_format_attribute;
/* Warn about traditional constructs whose meanings changed in ANSI C. */
/* Warn about #pragma directives that are not recognised. */
-int warn_unknown_pragmas = 0; /* Tri state variable. */
+int warn_unknown_pragmas = 0; /* Tri state variable. */
/* Warn about comparison of signed and unsigned values.
If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified. */
int warn_sign_compare = -1;
-/* Warn about testing equality of floating point numbers. */
+/* Warn about testing equality of floating point numbers. */
int warn_float_equal = 0;
int warn_multichar = 1;
-/* Wrapper since C and C++ expand_expr_stmt are different. */
-
-expand_expr_stmt_fn lang_expand_expr_stmt = c_expand_expr_stmt;
-
/* The variant of the C language being processed. */
c_language_kind c_language = clk_c;
/* Decode the string P as a language-specific option for C.
Return the number of strings consumed. Should not complain
if it does not recognise the option. */
-
+
int
c_decode_option (argc, argv)
int argc ATTRIBUTE_UNUSED;
char **argv;
{
int strings_processed;
+ const char *option_value = NULL;
char *p = argv[0];
-#if USE_CPPLIB
- strings_processed = cpp_handle_option (&parse_in, argc, argv);
-#else
- strings_processed = 0;
-#endif /* ! USE_CPPLIB */
+
+ strings_processed = cpp_handle_option (parse_in, argc, argv);
if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
{
flag_traditional = 1;
flag_writable_strings = 1;
- flag_digraphs = 0;
}
else if (!strcmp (p, "-fallow-single-precision"))
flag_allow_single_precision = 1;
{
flag_traditional = 0;
flag_writable_strings = 0;
- flag_digraphs = 1;
}
else if (!strncmp (p, "-std=", 5))
{
|| !strcmp (argstart, "c89"))
{
iso_1990:
- flag_digraphs = 0;
- iso_1990_digraphs:
+ flag_isoc94 = 0;
+ iso_1994:
flag_traditional = 0;
flag_writable_strings = 0;
flag_no_asm = 1;
flag_no_nonansi_builtin = 1;
+ flag_noniso_default_format_attributes = 0;
flag_isoc99 = 0;
}
else if (!strcmp (argstart, "iso9899:199409"))
{
- flag_digraphs = 1;
- /* ??? The other changes since ISO C 1990 are not supported. */
- goto iso_1990_digraphs;
+ flag_isoc94 = 1;
+ goto iso_1994;
}
else if (!strcmp (argstart, "iso9899:199x")
|| !strcmp (argstart, "iso9899:1999")
flag_writable_strings = 0;
flag_no_asm = 1;
flag_no_nonansi_builtin = 1;
+ flag_noniso_default_format_attributes = 0;
flag_isoc99 = 1;
- flag_digraphs = 1;
+ flag_isoc94 = 1;
}
else if (!strcmp (argstart, "gnu89"))
{
flag_writable_strings = 0;
flag_no_asm = 0;
flag_no_nonansi_builtin = 0;
+ flag_noniso_default_format_attributes = 1;
flag_isoc99 = 0;
- flag_digraphs = 1;
+ flag_isoc94 = 0;
}
else if (!strcmp (argstart, "gnu9x") || !strcmp (argstart, "gnu99"))
{
flag_writable_strings = 0;
flag_no_asm = 0;
flag_no_nonansi_builtin = 0;
+ flag_noniso_default_format_attributes = 1;
flag_isoc99 = 1;
- flag_digraphs = 1;
+ flag_isoc94 = 1;
}
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 (!strcmp (p, "-ansi"))
goto iso_1990;
else if (!strcmp (p, "-Werror-implicit-function-declaration"))
{
warn_implicit_int = 1;
if (mesg_implicit_function_declaration != 2)
- mesg_implicit_function_declaration = 1;
+ mesg_implicit_function_declaration = 1;
}
else if (!strcmp (p, "-Wno-implicit"))
warn_implicit_int = 0, mesg_implicit_function_declaration = 0;
warn_missing_noreturn = 1;
else if (!strcmp (p, "-Wno-missing-noreturn"))
warn_missing_noreturn = 0;
+ else if (!strcmp (p, "-Wmissing-format-attribute"))
+ warn_missing_format_attribute = 1;
+ else if (!strcmp (p, "-Wno-missing-format-attribute"))
+ warn_missing_format_attribute = 0;
else if (!strcmp (p, "-Wpointer-arith"))
warn_pointer_arith = 1;
else if (!strcmp (p, "-Wno-pointer-arith"))
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"))
warn_format = 1;
warn_char_subscripts = 1;
warn_parentheses = 1;
+ warn_sequence_point = 1;
warn_missing_braces = 1;
/* We set this to 2 here, but 1 in -Wmain, so -ffreestanding can turn
it off only if it's not explicit. */
print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4);
print_node (file, "limbo value", IDENTIFIER_LIMBO_VALUE (node), indent + 4);
+ if (C_IS_RESERVED_WORD (node))
+ {
+ tree rid = ridpointers[C_RID_CODE (node)];
+ indent_to (file, indent + 4);
+ fprintf (file, "rid ");
+ fprintf (file, HOST_PTR_PRINTF, (void *)rid);
+ fprintf (file, " \"%s\"", IDENTIFIER_POINTER (rid));
+ }
}
\f
/* Hook called at end of compilation to assume 1 elt
- for a top-level array decl that wasn't complete before. */
-
+ for a top-level tentative array defn that wasn't complete before. */
+
void
finish_incomplete_decl (decl)
tree decl;
tree type = TREE_TYPE (decl);
if (type != error_mark_node
&& TREE_CODE (type) == ARRAY_TYPE
+ && ! DECL_EXTERNAL (decl)
&& TYPE_DOMAIN (type) == 0)
{
- if (! DECL_EXTERNAL (decl))
- warning_with_decl (decl, "array `%s' assumed to have one element");
+ warning_with_decl (decl, "array `%s' assumed to have one element");
complete_array_type (type, NULL_TREE, 1);
\f
/* Create a new `struct binding_level'. */
-static
-struct binding_level *
+static struct binding_level *
make_binding_level ()
{
/* NOSTRICT */
keep_next_if_subblocks = 0;
}
-/* Clear the limbo values of all identifiers defined in BLOCK or a subblock. */
+/* Clear the limbo values of all identifiers defined in BLOCK or a subblock. */
static void
clear_limbo_values (block)
for (tem = BLOCK_SUBBLOCKS (block); tem; tem = TREE_CHAIN (tem))
clear_limbo_values (tem);
}
-
+
/* Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered.
if (DECL_ABSTRACT_ORIGIN (decl) != 0
&& DECL_ABSTRACT_ORIGIN (decl) != decl)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
- else if (DECL_SAVED_INSNS (decl) != 0)
- {
- push_function_context ();
- output_inline_function (decl);
- pop_function_context ();
- }
}
+ /* We used to warn about unused variables in expand_end_bindings,
+ i.e. while generating RTL. But in function-at-a-time mode we may
+ choose to never expand a function at all (e.g. auto inlining), so
+ we do this explicitly now. */
+ warn_about_unused_variables (getdecls ());
+
/* If there were any declarations or structure tags in that level,
or if this level is a function body,
create a BLOCK to record them for the life of this function. */
else if (block)
{
if (!block_previously_created)
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, block);
+ current_binding_level->blocks
+ = chainon (current_binding_level->blocks, block);
}
/* If we did not make a block for the level just exited,
any blocks made for inner levels
cases, the TYPE_CONTEXTs of the relevant tagged type nodes get set
in `grokdeclarator' as soon as we have created the FUNCTION_TYPE
node which will represent the "scope" for these "parameter list local"
- tagged types.
- */
+ tagged types. */
if (functionbody)
for (link = tags; link; link = TREE_CHAIN (link))
if (block)
TREE_USED (block) = 1;
+
return block;
}
DECL_NAME (TREE_VALUE (link)));
}
else if (warn_unused_label && !TREE_USED (TREE_VALUE (link)))
- warning_with_decl (TREE_VALUE (link),
+ warning_with_decl (TREE_VALUE (link),
"label `%s' defined but not used");
IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link))) = 0;
if (DECL_P (olddecl))
DECL_MACHINE_ATTRIBUTES (newdecl)
- = merge_machine_decl_attributes (olddecl, newdecl);
+ = merge_machine_decl_attributes (olddecl, newdecl);
if (TREE_CODE (newtype) == ERROR_MARK
|| TREE_CODE (oldtype) == ERROR_MARK)
"built-in function `%s' declared as non-function");
else
warning_with_decl (newdecl,
- "built-in function `%s' declared as non-function");
+ "built-in function `%s' declared as non-function");
}
else
{
}
else if (!types_match)
{
- /* Accept the return type of the new declaration if same modes. */
+ /* Accept the return type of the new declaration if same modes. */
tree oldreturntype = TREE_TYPE (oldtype);
tree newreturntype = TREE_TYPE (newtype);
- if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
- {
+ if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
+ {
/* Function types may be shared, so we can't just modify
the return type of olddecl's function type. */
tree trytype
= build_function_type (newreturntype,
TYPE_ARG_TYPES (oldtype));
-
+
types_match = comptypes (newtype, trytype);
if (types_match)
oldtype = trytype;
the return type of olddecl's function type. */
tree trytype
= build_function_type (TREE_TYPE (oldtype),
- tree_cons (NULL_TREE,
+ tree_cons (NULL_TREE,
TREE_VALUE (TYPE_ARG_TYPES (newtype)),
TREE_CHAIN (TYPE_ARG_TYPES (oldtype))));
-
- types_match = comptypes (newtype, trytype);
+
+ types_match = comptypes (newtype, trytype);
if (types_match)
oldtype = trytype;
}
: "`%s' previously declared here"));
}
else if (TREE_CODE (newdecl) == TYPE_DECL
- && (DECL_IN_SYSTEM_HEADER (olddecl)
+ && (DECL_IN_SYSTEM_HEADER (olddecl)
|| DECL_IN_SYSTEM_HEADER (newdecl)))
{
warning_with_decl (newdecl, "redefinition of `%s'");
- warning_with_decl
+ warning_with_decl
(olddecl,
((DECL_INITIAL (olddecl)
&& current_binding_level == global_binding_level)
if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
- error_with_decl (newdecl, "prototype for `%s' follows and number of arguments doesn't match");
+ error_with_decl (newdecl,
+ "prototype for `%s' follows and number of arguments doesn't match");
error_with_decl (olddecl, "non-prototype definition here");
errmsg = 1;
break;
warning_with_decl (newdecl, "static declaration for `%s' follows non-static");
/* If warn_traditional, warn when a non-static function
- declaration follows a static one. */
- if (warn_traditional
+ declaration follows a static one. */
+ if (warn_traditional && !in_system_header
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& !TREE_PUBLIC (olddecl)
&& TREE_PUBLIC (newdecl))
}
/* Merge the storage class information. */
- DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);
+ DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);
/* For functions, static overrides non-static. */
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
}
if (DECL_EXTERNAL (newdecl))
{
- TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
- DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
+ if (! different_binding_level)
+ {
+ /* Don't mess with these flags on local externs; they remain
+ external even if there's a declaration at file scope which
+ isn't. */
+ TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
+ DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
+ }
/* An extern decl does not override previous storage class. */
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
if (! DECL_EXTERNAL (newdecl))
}
}
if (different_binding_level)
- {
- /* Don't output a duplicate symbol or debugging information for this
- declaration.
-
- Do not set TREE_ASM_WRITTEN for a FUNCTION_DECL since we may actually
- just have two declarations without a definition. VAR_DECLs may need
- the same treatment, I'm not sure. */
- if (TREE_CODE (newdecl) == FUNCTION_DECL)
- DECL_IGNORED_P (newdecl) = 1;
- else
- TREE_ASM_WRITTEN (newdecl) = DECL_IGNORED_P (newdecl) = 1;
- return 0;
- }
+ return 0;
/* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
But preserve OLDDECL's DECL_UID. */
{
register unsigned olddecl_uid = DECL_UID (olddecl);
- bcopy ((char *) newdecl + sizeof (struct tree_common),
- (char *) olddecl + sizeof (struct tree_common),
- sizeof (struct tree_decl) - sizeof (struct tree_common));
+ memcpy ((char *) olddecl + sizeof (struct tree_common),
+ (char *) newdecl + sizeof (struct tree_common),
+ sizeof (struct tree_decl) - sizeof (struct tree_common));
DECL_UID (olddecl) = olddecl_uid;
}
/* A local extern declaration for a function doesn't constitute nesting.
A local auto declaration does, since it's a forward decl
for a nested function coming later. */
- if (TREE_CODE (x) == FUNCTION_DECL && DECL_INITIAL (x) == 0
- && DECL_EXTERNAL (x))
+ if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
+ && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
DECL_CONTEXT (x) = 0;
if (warn_nested_externs && DECL_EXTERNAL (x) && b != global_binding_level
on a standard type by checking the current value of lineno. */
if (TREE_CODE (x) == TYPE_DECL)
- {
- if (DECL_SOURCE_LINE (x) == 0)
- {
+ {
+ if (DECL_SOURCE_LINE (x) == 0)
+ {
if (TYPE_NAME (TREE_TYPE (x)) == 0)
- TYPE_NAME (TREE_TYPE (x)) = x;
- }
- else if (TREE_TYPE (x) != error_mark_node
+ TYPE_NAME (TREE_TYPE (x)) = x;
+ }
+ else if (TREE_TYPE (x) != error_mark_node
&& DECL_ORIGINAL_TYPE (x) == NULL_TREE)
- {
- tree tt = TREE_TYPE (x);
+ {
+ tree tt = TREE_TYPE (x);
DECL_ORIGINAL_TYPE (x) = tt;
- tt = build_type_copy (tt);
- TYPE_NAME (tt) = x;
+ tt = build_type_copy (tt);
+ TYPE_NAME (tt) = x;
TREE_USED (tt) = TREE_USED (x);
- TREE_TYPE (x) = tt;
- }
- }
+ TREE_TYPE (x) = tt;
+ }
+ }
/* Multiple external decls of the same identifier ought to match.
Check against both global declarations (when traditional) and out of
if (b == global_binding_level)
{
/* Install a global value. */
-
+
/* If the first global decl has external linkage,
warn if we later see static one. */
if (IDENTIFIER_GLOBAL_VALUE (name) == 0 && TREE_PUBLIC (x))
DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
DECL_RESULT (x) = DECL_RESULT (oldglobal);
TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
- DECL_ABSTRACT_ORIGIN (x) = DECL_ORIGIN (oldglobal);
+ DECL_ABSTRACT_ORIGIN (x)
+ = DECL_ABSTRACT_ORIGIN (oldglobal);
}
/* Inner extern decl is built-in if global one is. */
if (DECL_BUILT_IN (oldglobal))
}
}
-#if 0 /* This case is probably sometimes the right thing to do. */
+#if 0
+ /* This case is probably sometimes the right thing to do. */
/* If we have a local external declaration,
then any file-scope declaration should not
have been static. */
&& TREE_PUBLIC (x))
{
if (oldglobal == 0)
- TREE_PUBLIC (name) = 1;
+ TREE_PUBLIC (name) = 1;
/* Save this decl, so that we can do type checking against
other decls after it falls out of scope.
/* No shadow warnings for vars made for inlining. */
&& ! DECL_FROM_INLINE (x))
{
- char *id = IDENTIFIER_POINTER (name);
+ const char *id = IDENTIFIER_POINTER (name);
if (TREE_CODE (x) == PARM_DECL
&& current_binding_level->level_chain->parm_flag)
/* We used to reuse an old implicit decl here,
but this loses with inline functions because it can clobber
the saved decl chains. */
-/* if (IDENTIFIER_IMPLICIT_DECL (functionid) != 0)
+#if 0
+ if (IDENTIFIER_IMPLICIT_DECL (functionid) != 0)
decl = IDENTIFIER_IMPLICIT_DECL (functionid);
- else */
+ else
+#endif
decl = build_decl (FUNCTION_DECL, functionid, default_function_type);
/* Warn of implicit decl following explicit local extern decl.
rest_of_decl_compilation (decl, NULL_PTR, 0, 0);
- if (mesg_implicit_function_declaration && implicit_warning)
- {
- if (mesg_implicit_function_declaration == 2)
- error ("implicit declaration of function `%s'",
- IDENTIFIER_POINTER (functionid));
- else
- warning ("implicit declaration of function `%s'",
- IDENTIFIER_POINTER (functionid));
- }
+ if (implicit_warning)
+ implicit_decl_warning (functionid);
else if (warn_traditional && traditional_warning)
warning ("function `%s' was previously declared within a block",
IDENTIFIER_POINTER (functionid));
return decl;
}
+void
+implicit_decl_warning (id)
+ tree id;
+{
+ const char *name = IDENTIFIER_POINTER (id);
+ if (mesg_implicit_function_declaration == 2)
+ error ("implicit declaration of function `%s'", name);
+ else if (mesg_implicit_function_declaration == 1)
+ warning ("implicit declaration of function `%s'", name);
+}
+
/* Return zero if the declaration NEWDECL is valid
when the declaration OLDDECL (assumed to be for the same name)
has already been seen.
is equivalent to what this code used to do before the build_type_copy
call. The variant type distinction should not matter for traditional
code, because it doesn't have type qualifiers. */
- if (flag_traditional
+ if (flag_traditional
&& TYPE_MAIN_VARIANT (TREE_TYPE (olddecl)) == TREE_TYPE (newdecl))
return 0;
if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl))
return 1;
return 0;
}
- else if (current_binding_level == global_binding_level)
+ else if (DECL_CONTEXT (newdecl) == NULL_TREE)
{
/* Objects declared at top level: */
/* If at least one is a reference, it's ok. */
decl = build_decl (LABEL_DECL, id, void_type_node);
- /* Make sure every label has an rtx. */
- label_rtx (decl);
-
/* A label not explicitly declared must be local to where it's ref'd. */
DECL_CONTEXT (decl) = current_function_decl;
for (dup = named_labels; dup; dup = TREE_CHAIN (dup))
if (TREE_VALUE (dup) == decl)
{
- error ("duplicate label declaration `%s'",
+ error ("duplicate label declaration `%s'",
IDENTIFIER_POINTER (name));
error_with_decl (TREE_VALUE (dup),
"this is a previous declaration");
decl = lookup_label (name);
}
- if (warn_traditional && lookup_name (name))
- warning ("traditional C lacks a separate namespace for labels, identifier `%s' conflicts",
- IDENTIFIER_POINTER (name));
-
+ if (warn_traditional && !in_system_header && lookup_name (name))
+ warning_with_file_and_line (filename, line,
+ "traditional C lacks a separate namespace for labels, identifier `%s' conflicts",
+ IDENTIFIER_POINTER (name));
+
if (DECL_INITIAL (decl) != 0)
{
- error ("duplicate label `%s'", IDENTIFIER_POINTER (name));
+ error_with_file_and_line (filename, line, "duplicate label `%s'",
+ IDENTIFIER_POINTER (name));
return 0;
}
else
tree name;
{
register tree val;
+
if (current_binding_level != global_binding_level
&& IDENTIFIER_LOCAL_VALUE (name))
val = IDENTIFIER_LOCAL_VALUE (name);
\f
/* Mark ARG for GC. */
-static void
+static void
mark_binding_level (arg)
void *arg;
{
named_labels = NULL;
current_binding_level = NULL_BINDING_LEVEL;
free_binding_level = NULL_BINDING_LEVEL;
- pushlevel (0); /* make the binding_level structure for global names */
+
+ /* Make the binding_level structure for global names. */
+ pushlevel (0);
global_binding_level = current_binding_level;
build_common_tree_nodes (flag_signed_char);
Note that stddef.h uses `unsigned long',
and this must agree, even if long and int are the same size. */
t = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)));
+ signed_size_type_node = signed_type (t);
if (flag_traditional && TREE_UNSIGNED (t))
t = signed_type (t);
-
+
+ c_size_type_node = t;
set_sizetype (t);
- /* Create the widest literal types. */
+ /* Create the widest literal types. */
widest_integer_literal_type_node
= make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
widest_unsigned_literal_type_node
= make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
- pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ pushdecl (build_decl (TYPE_DECL, NULL_TREE,
widest_integer_literal_type_node));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ pushdecl (build_decl (TYPE_DECL, NULL_TREE,
widest_unsigned_literal_type_node));
build_common_tree_nodes_2 (flag_short_double);
signed_wchar_type_node = signed_type (wchar_type_node);
unsigned_wchar_type_node = unsigned_type (wchar_type_node);
+ wint_type_node =
+ TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WINT_TYPE)));
+
+ intmax_type_node =
+ TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (INTMAX_TYPE)));
+ uintmax_type_node =
+ TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (UINTMAX_TYPE)));
+
boolean_type_node = integer_type_node;
boolean_true_node = integer_one_node;
boolean_false_node = integer_zero_node;
+ /* With GCC, C99's _Bool is always of size 1. */
+ c_bool_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
+ TREE_SET_CODE (c_bool_type_node, BOOLEAN_TYPE);
+ TYPE_MAX_VALUE (c_bool_type_node) = build_int_2 (1, 0);
+ TREE_TYPE (TYPE_MAX_VALUE (c_bool_type_node)) = c_bool_type_node;
+ TYPE_PRECISION (c_bool_type_node) = 1;
+ pushdecl (build_decl (TYPE_DECL, get_identifier ("_Bool"),
+ c_bool_type_node));
+ c_bool_false_node = build_int_2 (0, 0);
+ TREE_TYPE (c_bool_false_node) = c_bool_type_node;
+ c_bool_true_node = build_int_2 (1, 0);
+ TREE_TYPE (c_bool_true_node) = c_bool_type_node;
+
string_type_node = build_pointer_type (char_type_node);
const_string_type_node
= build_pointer_type (build_type_variant (char_type_node, 1, 0));
/* make a type for arrays of characters.
With luck nothing will ever really depend on the length of this
array type. */
- char_array_type_node
- = build_array_type (char_type_node, array_domain_type);
+ char_array_type_node = build_array_type (char_type_node, array_domain_type);
/* Likewise for arrays of ints. */
int_array_type_node
void_list_node = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
- default_function_type
- = build_function_type (integer_type_node, NULL_TREE);
+ default_function_type = build_function_type (integer_type_node, NULL_TREE);
ptrdiff_type_node
= TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
+ unsigned_ptrdiff_type_node = unsigned_type (ptrdiff_type_node);
- c_common_nodes_and_builtins (0, flag_no_builtin, flag_no_nonansi_builtin);
+ c_common_nodes_and_builtins ();
endlink = void_list_node;
ptr_ftype_void = build_function_type (ptr_type_node, endlink);
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. */
+ changing these, you also need to be concerned with f/com.h. */
if (TYPE_PRECISION (float_type_node)
== TYPE_PRECISION (long_integer_type_node))
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE,
type_for_mode (ptr_mode, 0),
- tree_cons (NULL_TREE,
+ tree_cons (NULL_TREE,
ptr_type_node,
endlink)))),
BUILT_IN_EH_RETURN, BUILT_IN_NORMAL, NULL_PTR);
pedantic_lvalues = pedantic;
- /* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */
+ /* Create the global bindings for __FUNCTION__, __PRETTY_FUNCTION__,
+ and __func__. */
+ function_id_node = get_identifier ("__FUNCTION__");
+ pretty_function_id_node = get_identifier ("__PRETTY_FUNCTION__");
+ func_id_node = get_identifier ("__func__");
make_fname_decl = c_make_fname_decl;
declare_function_name ();
/* Prepare to check format strings against argument lists. */
init_function_format_info ();
- init_iterators ();
-
incomplete_decl_finalize_hook = finish_incomplete_decl;
/* Record our roots. */
ggc_add_tree_root (c_global_trees, CTI_MAX);
+ ggc_add_root (&c_stmt_tree, 1, sizeof c_stmt_tree, mark_stmt_tree);
+ ggc_add_tree_root (&c_scope_stmt_stack, 1);
ggc_add_tree_root (&named_labels, 1);
ggc_add_tree_root (&shadowed_labels, 1);
ggc_add_root (¤t_binding_level, 1, sizeof current_binding_level,
delayed emission of static data, we mark the decl as emitted
so it is not placed in the output. Anything using it must therefore pull
out the STRING_CST initializer directly. This does mean that these names
- are string merging candidates, which C99 does not permit. */
+ are string merging candidates, which is wrong for C99's __func__. FIXME. */
static tree
c_make_fname_decl (id, name, type_dep)
TREE_TYPE (init) = type;
DECL_INITIAL (decl) = init;
finish_decl (pushdecl (decl), init, NULL_TREE);
-
+
return decl;
}
NORMAL, initialized);
register tree tem;
- if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
- && !strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "main"))
+ if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
+ && MAIN_NAME_P (DECL_NAME (decl)))
warning_with_decl (decl, "`%s' is usually a function");
if (initialized)
default:
/* Don't allow initializations for incomplete types
except for arrays which might be completed by the initialization. */
- if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
+
+ /* This can happen if the array size is an undefined macro. We already
+ gave a warning, so we don't need another one. */
+ if (TREE_TYPE (decl) == error_mark_node)
+ initialized = 0;
+ else if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
{
/* A complete type is ok if size is fixed. */
if (initialized)
{
-#if 0 /* Seems redundant with grokdeclarator. */
+#if 0
+ /* Seems redundant with grokdeclarator. */
if (current_binding_level != global_binding_level
&& DECL_EXTERNAL (decl)
&& TREE_CODE (decl) != FUNCTION_DECL)
/* But not if this is a duplicate decl
and we preserved the rtl from the previous one
(which may or may not happen). */
- && DECL_RTL (tem) == 0)
+ && DECL_RTL (tem) == 0
+ && !DECL_CONTEXT (tem))
{
- if (COMPLETE_TYPE_P (TREE_TYPE (tem)))
+ if (TREE_TYPE (tem) != error_mark_node
+ && COMPLETE_TYPE_P (TREE_TYPE (tem)))
expand_decl (tem);
else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
&& DECL_INITIAL (tem) != 0)
{
register tree type = TREE_TYPE (decl);
int was_incomplete = (DECL_SIZE (decl) == 0);
- char *asmspec = 0;
+ const char *asmspec = 0;
/* If a name was specified, get the string. */
if (asmspec_tree)
if (TREE_CODE (decl) == PARM_DECL)
init = 0;
- if (ITERATOR_P (decl))
- {
- if (init == 0)
- error_with_decl (decl, "iterator has no initial value");
- else
- init = save_expr (init);
- }
-
if (init)
{
if (TREE_CODE (decl) != TYPE_DECL)
if (failure == 1)
error_with_decl (decl, "initializer fails to determine size of `%s'");
- if (failure == 2)
+ else if (failure == 2)
{
if (do_default)
error_with_decl (decl, "array size missing in `%s'");
/* TYPE_MAX_VALUE is always one less than the number of elements
in the array, because we start counting at zero. Therefore,
warn only if the value is less than zero. */
- if (pedantic && TYPE_DOMAIN (type) != 0
- && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
+ else if (pedantic && TYPE_DOMAIN (type) != 0
+ && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
error_with_decl (decl, "zero or negative size array `%s'");
layout_decl (decl, 0);
if (TREE_CODE (decl) == VAR_DECL)
{
- if (DECL_SIZE (decl) == 0 && COMPLETE_TYPE_P (TREE_TYPE (decl)))
+ if (DECL_SIZE (decl) == 0 && TREE_TYPE (decl) != error_mark_node
+ && COMPLETE_TYPE_P (TREE_TYPE (decl)))
layout_decl (decl, 0);
if (DECL_SIZE (decl) == 0
+ /* Don't give an error if we already gave one earlier. */
+ && TREE_TYPE (decl) != error_mark_node
&& (TREE_STATIC (decl)
?
/* A static variable with an incomplete type
Also if it is not file scope.
Otherwise, let it through, but if it is not `extern'
then it may cause an error message later. */
- /* A duplicate_decls call could have changed an extern
- declaration into a file scope one. This can be detected
- by TREE_ASM_WRITTEN being set. */
(DECL_INITIAL (decl) != 0
- || (DECL_CONTEXT (decl) != 0 && ! TREE_ASM_WRITTEN (decl)))
+ || DECL_CONTEXT (decl) != 0)
:
/* An automatic variable with an incomplete type
is an error. */
error_with_decl (decl, "storage size of `%s' isn't constant");
}
- if (TREE_USED (type))
+ if (TREE_USED (type))
TREE_USED (decl) = 1;
}
builtin any more. Also reset DECL_RTL so we can give it its new
name. */
if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
- {
- DECL_BUILT_IN_CLASS (decl) = NOT_BUILT_IN;
- DECL_RTL (decl) = 0;
- DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
- }
+ {
+ DECL_BUILT_IN_CLASS (decl) = NOT_BUILT_IN;
+ DECL_RTL (decl) = 0;
+ DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
+ }
/* Output the assembler code and/or RTL code for variables and functions,
unless the type is an undefined structure or union.
{
/* This is a no-op in c-lang.c or something real in objc-actions.c. */
maybe_objc_check_decl (decl);
- rest_of_decl_compilation (decl, asmspec,
- (DECL_CONTEXT (decl) == 0
- || TREE_ASM_WRITTEN (decl)), 0);
+
+ if (!DECL_CONTEXT (decl))
+ rest_of_decl_compilation (decl, asmspec,
+ (DECL_CONTEXT (decl) == 0
+ || TREE_ASM_WRITTEN (decl)), 0);
+ else
+ {
+ if (asmspec)
+ {
+ DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
+ DECL_C_HARD_REGISTER (decl) = 1;
+ }
+ add_decl_stmt (decl);
+ }
if (DECL_CONTEXT (decl) != 0)
{
/* If it's still incomplete now, no init will save it. */
if (DECL_SIZE (decl) == 0)
DECL_INITIAL (decl) = 0;
- expand_decl (decl);
}
- /* Compute and store the initial value. */
- if (TREE_CODE (decl) != FUNCTION_DECL)
- expand_decl_init (decl);
}
}
tree olddecl;
olddecl = lookup_name (DECL_NAME (decl));
if (pedantic && olddecl != 0 && TREE_CODE (olddecl) == TYPE_DECL)
- pedwarn_with_decl (decl, "ANSI C forbids parameter `%s' shadowing typedef");
+ pedwarn_with_decl (decl,
+ "ANSI C forbids parameter `%s' shadowing typedef");
}
#endif
for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
{
- register int i;
register tree id = TREE_VALUE (spec);
if (id == ridpointers[(int) RID_INT])
if (id == ridpointers[(int) RID_CHAR])
explicit_char = 1;
- if (TREE_CODE (id) == IDENTIFIER_NODE)
- for (i = (int) RID_FIRST_MODIFIER; i < (int) RID_MAX; i++)
- {
- if (ridpointers[i] == id)
- {
- if (i == (int) RID_LONG && specbits & (1<<i))
- {
- if (longlong)
- error ("`long long long' is too long for GCC");
- else
- {
- if (pedantic && !flag_isoc99 && ! in_system_header
- && warn_long_long)
- pedwarn ("ANSI C does not support `long long'");
- longlong = 1;
- }
- }
- else if (specbits & (1 << i))
- pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
- specbits |= 1 << i;
- goto found;
- }
- }
+ if (TREE_CODE (id) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (id))
+ {
+ enum rid i = C_RID_CODE (id);
+ if (i <= RID_LAST_MODIFIER)
+ {
+ if (i == RID_LONG && specbits & (1<<i))
+ {
+ if (longlong)
+ error ("`long long long' is too long for GCC");
+ else
+ {
+ if (pedantic && !flag_isoc99 && ! in_system_header
+ && warn_long_long)
+ pedwarn ("ISO C89 does not support `long long'");
+ longlong = 1;
+ }
+ }
+ else if (specbits & (1 << i))
+ pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
+ specbits |= 1 << i;
+ goto found;
+ }
+ }
if (type)
error ("two or more data types in declaration of `%s'", name);
/* Actual typedefs come to us as TYPE_DECL nodes. */
else if (TREE_CODE (id) == TYPE_DECL)
{
type = TREE_TYPE (id);
- decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
+ decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
typedef_decl = id;
}
/* Built-in types come as identifiers. */
else if (TREE_CODE (id) != ERROR_MARK)
type = id;
- found: {}
+ found:
+ ;
}
typedef_type = type;
{
if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
| (1 << (int) RID_SIGNED)
- | (1 << (int) RID_UNSIGNED))))
+ | (1 << (int) RID_UNSIGNED)
+ | (1 << (int) RID_COMPLEX))))
/* Don't warn about typedef foo = bar. */
&& ! (specbits & (1 << (int) RID_TYPEDEF) && initialized)
&& ! in_system_header)
if ((warn_implicit_int || warn_return_type) && funcdef_flag)
warn_about_return_type = 1;
else if (warn_implicit_int || flag_isoc99)
- pedwarn_c99 ("type defaults to `int' in declaration of `%s'", name);
+ pedwarn_c99 ("type defaults to `int' in declaration of `%s'",
+ name);
}
defaulted_int = 1;
if ((specbits & 1 << (int) RID_LONG) && ! longlong
&& TYPE_MAIN_VARIANT (type) == double_type_node)
{
- specbits &= ~ (1 << (int) RID_LONG);
+ specbits &= ~(1 << (int) RID_LONG);
type = long_double_type_node;
}
&& TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
{
error ("complex invalid for `%s'", name);
- specbits &= ~ (1 << (int) RID_COMPLEX);
+ specbits &= ~(1 << (int) RID_COMPLEX);
}
/* Decide whether an integer type is signed or not.
if (specbits & 1 << (int) RID_COMPLEX)
{
+ if (pedantic && !flag_isoc99)
+ pedwarn ("ISO C89 does not support complex types");
/* If we just have "complex", it is equivalent to
"complex double", but if any modifiers at all are specified it is
the complex form of TYPE. E.g, "complex short" is
&& ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
| (1 << (int) RID_SIGNED)
| (1 << (int) RID_UNSIGNED))))
- type = complex_double_type_node;
+ {
+ if (pedantic)
+ pedwarn ("ISO C does not support plain `complex' meaning `double complex'");
+ type = complex_double_type_node;
+ }
else if (type == integer_type_node)
- type = complex_integer_type_node;
+ {
+ if (pedantic)
+ pedwarn ("ISO C does not support complex integer types");
+ type = complex_integer_type_node;
+ }
else if (type == float_type_node)
type = complex_float_type_node;
else if (type == double_type_node)
else if (type == long_double_type_node)
type = complex_long_double_type_node;
else
- type = build_complex_type (type);
+ {
+ if (pedantic)
+ pedwarn ("ISO C does not support complex integer types");
+ type = build_complex_type (type);
+ }
}
/* Figure out the type qualifiers for the declaration. There are
if (specbits & 1 << (int) RID_EXTERN) nclasses++;
if (specbits & 1 << (int) RID_REGISTER) nclasses++;
if (specbits & 1 << (int) RID_TYPEDEF) nclasses++;
- if (specbits & 1 << (int) RID_ITERATOR) nclasses++;
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
error ("function definition declared `register'");
if (specbits & 1 << (int) RID_TYPEDEF)
error ("function definition declared `typedef'");
- specbits &= ~ ((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
- | (1 << (int) RID_AUTO));
+ specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
+ | (1 << (int) RID_AUTO));
}
else if (decl_context != NORMAL && nclasses > 0)
{
switch (decl_context)
{
case FIELD:
- error ("storage class specified for structure field `%s'", name);
+ error ("storage class specified for structure field `%s'",
+ name);
break;
case PARM:
error ("storage class specified for parameter `%s'", name);
error ("storage class specified for typename");
break;
}
- specbits &= ~ ((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
- | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
- | (1 << (int) RID_EXTERN));
+ specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
+ | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
+ | (1 << (int) RID_EXTERN));
}
}
else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
else if (current_binding_level == global_binding_level
&& specbits & (1 << (int) RID_AUTO))
error ("top-level declaration of `%s' specifies `auto'", name);
- else if ((specbits & 1 << (int) RID_ITERATOR)
- && TREE_CODE (declarator) != IDENTIFIER_NODE)
- {
- error ("iterator `%s' has derived type", name);
- type = error_mark_node;
- }
- else if ((specbits & 1 << (int) RID_ITERATOR)
- && TREE_CODE (type) != INTEGER_TYPE)
- {
- error ("iterator `%s' has noninteger type", name);
- type = error_mark_node;
- }
}
/* Now figure out the structure of the declarator proper.
}
if (pedantic && integer_zerop (size))
- pedwarn ("ANSI C forbids zero-size array `%s'", name);
+ pedwarn ("ISO C forbids zero-size array `%s'", name);
if (TREE_CODE (size) == INTEGER_CST)
{
if (pedantic)
{
if (TREE_CONSTANT (size))
- pedwarn ("ANSI C forbids array `%s' whose size can't be evaluated", name);
+ pedwarn ("ISO C89 forbids array `%s' whose size can't be evaluated",
+ name);
else
- pedwarn ("ANSI C forbids variable-size array `%s'", name);
+ pedwarn ("ISO C89 forbids variable-size array `%s'",
+ name);
}
}
- /* Convert size to index_type, so that if it is a variable
- the computations will be done in the proper mode. */
- itype = fold (build (MINUS_EXPR, index_type,
- convert (index_type, size),
- convert (index_type, size_one_node)));
-
- /* If that overflowed, the array is too big.
- ??? While a size of INT_MAX+1 technically shouldn't cause
- an overflow (because we subtract 1), the overflow is recorded
- during the conversion to index_type, before the subtraction.
- Handling this case seems like an unnecessary complication. */
- if (TREE_OVERFLOW (itype))
+ if (integer_zerop (size))
{
- error ("size of array `%s' is too large", name);
- type = error_mark_node;
- continue;
+ /* A zero-length array cannot be represented with an
+ unsigned index type, which is what we'll get with
+ build_index_type. Create an open-ended range instead. */
+ itype = build_range_type (sizetype, size, NULL_TREE);
}
+ else
+ {
+ /* Compute the maximum valid index, that is, size - 1.
+ Do the calculation in index_type, so that if it is
+ a variable the computations will be done in the
+ proper mode. */
+ itype = fold (build (MINUS_EXPR, index_type,
+ convert (index_type, size),
+ convert (index_type, size_one_node)));
+
+ /* If that overflowed, the array is too big.
+ ??? While a size of INT_MAX+1 technically shouldn't
+ cause an overflow (because we subtract 1), the overflow
+ is recorded during the conversion to index_type, before
+ the subtraction. Handling this case seems like an
+ unnecessary complication. */
+ if (TREE_OVERFLOW (itype))
+ {
+ error ("size of array `%s' is too large", name);
+ type = error_mark_node;
+ continue;
+ }
- if (size_varies)
- itype = variable_size (itype);
- itype = build_index_type (itype);
+ if (size_varies)
+ itype = variable_size (itype);
+ itype = build_index_type (itype);
+ }
}
+ else if (decl_context == FIELD)
+ {
+ /* ??? Need to check somewhere that this is a structure
+ and not a union, that this field is last, and that
+ this structure has at least one other named member. */
-#if 0 /* This had bad results for pointers to arrays, as in
- union incomplete (*foo)[4]; */
+ if (pedantic && !flag_isoc99 && !in_system_header)
+ pedwarn ("ISO C89 does not support flexible array members");
+
+ /* ISO C99 Flexible array members are effectively identical
+ to GCC's zero-length array extension. */
+ itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+ }
+
+#if 0
+ /* This had bad results for pointers to arrays, as in
+ union incomplete (*foo)[4]; */
/* Complain about arrays of incomplete types, except in typedefs. */
if (!COMPLETE_TYPE_P (type)
warning ("array type has incomplete element type");
#endif
-#if 0 /* We shouldn't have a function type here at all!
- Functions aren't allowed as array elements. */
+#if 0
+ /* We shouldn't have a function type here at all!
+ Functions aren't allowed as array elements. */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& (constp || volatilep))
pedwarn ("ANSI C forbids const or volatile function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
-#if 0 /* don't clear these; leave them set so that the array type
- or the variable is itself const or volatile. */
+#if 0
+ /* Don't clear these; leave them set so that the array type
+ or the variable is itself const or volatile. */
type_quals = TYPE_UNQUALIFIED;
#endif
/* Type qualifiers before the return type of the function
qualify the return type, not the function type. */
if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ {
+ /* Type qualifiers on a function return type are normally
+ permitted by the standard but have no effect, so give a
+ warning at -W. Qualifiers on a void return type have
+ meaning as a GNU extension, and are banned on function
+ definitions in ISO C. FIXME: strictly we shouldn't
+ pedwarn for qualified void return types except on function
+ definitions, but not doing so could lead to the undesirable
+ state of a "volatile void" function return type not being
+ warned about, and a use of the function being compiled
+ with GNU semantics, with no diagnostics under -pedantic. */
+ if (VOID_TYPE_P (type) && pedantic && !in_system_header)
+ pedwarn ("ISO C forbids qualified void function return type");
+ else if (extra_warnings
+ && !(VOID_TYPE_P (type)
+ && type_quals == TYPE_QUAL_VOLATILE))
+ warning ("type qualifiers ignored on function return type");
+
+ type = c_build_qualified_type (type, type_quals);
+ }
type_quals = TYPE_UNQUALIFIED;
type = build_function_type (type, arg_types);
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn ("ANSI C forbids qualified function types");
+ pedwarn ("ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
type_quals = TYPE_UNQUALIFIED;
{
tree qualifier = TREE_VALUE (typemodlist);
- if (qualifier == ridpointers[(int) RID_CONST])
- constp++;
- else if (qualifier == ridpointers[(int) RID_VOLATILE])
- volatilep++;
- else if (qualifier == ridpointers[(int) RID_RESTRICT])
- restrictp++;
- else if (!erred)
+ if (C_IS_RESERVED_WORD (qualifier))
{
- erred = 1;
- error ("invalid type modifier within pointer declarator");
+ if (C_RID_CODE (qualifier) == RID_CONST)
+ constp++;
+ else if (C_RID_CODE (qualifier) == RID_VOLATILE)
+ volatilep++;
+ else if (C_RID_CODE (qualifier) == RID_RESTRICT)
+ restrictp++;
+ else
+ erred++;
}
+ else
+ erred++;
}
+
+ if (erred)
+ error ("invalid type modifier within pointer declarator");
if (constp > 1 && ! flag_isoc99)
pedwarn ("duplicate `const'");
if (volatilep > 1 && ! flag_isoc99)
in typenames, fields or parameters */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn ("ANSI C forbids qualified function types");
+ pedwarn ("ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
decl = build_decl (TYPE_DECL, declarator, type);
controlled separately by its own initializer. */
if (type != 0 && typedef_type != 0
- && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type)
- && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0)
+ && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0
+ && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
{
type = build_array_type (TREE_TYPE (type), 0);
if (size_varies)
in typenames, fields or parameters */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn ("ANSI C forbids const or volatile function types");
+ pedwarn ("ISO C forbids const or volatile function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
return type;
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
if (pedantic && type_quals)
- pedwarn ("ANSI C forbids qualified function types");
+ pedwarn ("ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
type_quals),
TYPE_DOMAIN (type));
-#if 0 /* Leave the field const or volatile as well. */
+#if 0
+ /* Leave the field const or volatile as well. */
type_quals = TYPE_UNQUALIFIED;
#endif
}
decl = build_decl_attribute_variant (decl, decl_machine_attr);
if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
- pedwarn ("ANSI C forbids qualified function types");
-
- if (pedantic
- && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
- && TYPE_QUALS (TREE_TYPE (TREE_TYPE (decl)))
- && ! DECL_IN_SYSTEM_HEADER (decl))
- pedwarn ("ANSI C forbids qualified void function return type");
+ pedwarn ("ISO C forbids qualified function types");
/* GNU C interprets a `volatile void' return type to indicate
that the function does not return. */
/* Record presence of `inline', if it is reasonable. */
if (inlinep)
{
- if (! strcmp (IDENTIFIER_POINTER (declarator), "main"))
+ if (MAIN_NAME_P (declarator))
warning ("cannot inline function `main'");
else
/* Assume that otherwise the function can be inlined. */
TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
-
- if (specbits & 1 << (int) RID_ITERATOR)
- ITERATOR_P (decl) = 1;
}
/* Record `register' declaration for warnings on &
TREE_TYPE (parm) = error_mark_node;
}
}
-#if 0 /* This has been replaced by parm_tags_warning
- which uses a more accurate criterion for what to warn about. */
+#if 0
+ /* This has been replaced by parm_tags_warning, which
+ uses a more accurate criterion for what to warn
+ about. */
else
{
/* Now warn if is a pointer to an incomplete type. */
typelt = TREE_CHAIN (typelt);
}
- return first_parm;
+ return first_parm;
}
}
-
/* Return a tree_list node with info on a parameter list just parsed.
The TREE_PURPOSE is a chain of decls of those parms.
The TREE_VALUE is a list of structure, union and enum tags defined.
tree new_parms = 0;
tree order = current_binding_level->parm_order;
- /* Just `void' (and no ellipsis) is special. There are really no parms. */
+ /* Just `void' (and no ellipsis) is special. There are really no parms.
+ But if the `void' is qualified (by `const' or `volatile') or has a
+ storage class specifier (`register'), then the behavior is undefined;
+ by not counting it as the special case of `void' we will cause an
+ error later. Typedefs for `void' are OK (see DR#157). */
if (void_at_end && parms != 0
&& TREE_CHAIN (parms) == 0
&& VOID_TYPE_P (TREE_TYPE (parms))
+ && ! TREE_THIS_VOLATILE (parms)
+ && ! TREE_READONLY (parms)
+ && ! DECL_REGISTER (parms)
&& DECL_NAME (parms) == 0)
{
parms = NULL_TREE;
/* Extract enumerator values and other non-parms declared with the parms.
Likewise any forward parm decls that didn't have real parm decls. */
- for (decl = parms; decl; )
+ for (decl = parms; decl;)
{
tree next = TREE_CHAIN (decl);
}
else if (TREE_ASM_WRITTEN (decl))
{
- error_with_decl (decl, "parameter `%s' has just a forward declaration");
+ error_with_decl (decl,
+ "parameter `%s' has just a forward declaration");
TREE_CHAIN (decl) = new_parms;
new_parms = decl;
}
: "enum"),
IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
else
- {
- /* For translation these need to be seperate warnings */
- if (code == RECORD_TYPE)
+ {
+ /* For translation these need to be seperate warnings */
+ if (code == RECORD_TYPE)
warning ("anonymous struct declared inside parameter list");
else if (code == UNION_TYPE)
warning ("anonymous union declared inside parameter list");
- else
+ else
warning ("anonymous enum declared inside parameter list");
}
if (! already)
{
/* (In ANSI, Enums can be referred to only if already defined.) */
if (pedantic)
- pedwarn ("ANSI C forbids forward references to `enum' types");
+ pedwarn ("ISO C forbids forward references to `enum' types");
/* Give the type a default layout like unsigned int
to avoid crashing if it does not get defined. */
TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
/* Detect invalid bit-field type. */
if (DECL_INITIAL (x)
&& TREE_CODE (TREE_TYPE (x)) != INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (x)) != BOOLEAN_TYPE
&& TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE)
{
error_with_decl (x, "bit-field `%s' has invalid type");
if (DECL_INITIAL (x) && pedantic
&& TYPE_MAIN_VARIANT (TREE_TYPE (x)) != integer_type_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (x)) != unsigned_type_node
+ && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != c_bool_type_node
/* Accept an enum that's equivalent to int or unsigned int. */
&& !(TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (x))
== TYPE_PRECISION (integer_type_node))))
- pedwarn_with_decl (x, "bit-field `%s' type invalid in ANSI C");
+ pedwarn_with_decl (x, "bit-field `%s' type invalid in ISO C");
/* Detect and ignore out of range field width and process valid
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));
if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
error_with_decl (x, "negative width in bit-field `%s'");
- else if (0 < compare_tree_int (DECL_INITIAL (x),
- TYPE_PRECISION (TREE_TYPE (x))))
+ else if (0 < compare_tree_int (DECL_INITIAL (x), max_width))
pedwarn_with_decl (x, "width of `%s' exceeds its type");
else if (integer_zerop (DECL_INITIAL (x)) && DECL_NAME (x) != 0)
error_with_decl (x, "zero width for bit-field `%s'");
"`%s' is narrower than values of its type");
DECL_SIZE (x) = bitsize_int (width);
- DECL_BIT_FIELD (x) = DECL_C_BIT_FIELD (x) = 1;
+ DECL_BIT_FIELD (x) = 1;
+ SET_DECL_C_BIT_FIELD (x);
if (width == 0)
{
else
{
register tree y = fieldlist;
-
+
while (1)
{
if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x)))
error_with_decl (TREE_CHAIN (x), "duplicate member `%s'");
TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
}
- else x = TREE_CHAIN (x);
+ else
+ x = TREE_CHAIN (x);
}
/* Now we have the nearly final fieldlist. Record it,
tree decl;
for (decl = current_binding_level->names; decl; decl = TREE_CHAIN (decl))
{
- if (TREE_TYPE (decl) == t
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TYPE_MAIN_VARIANT (t)
&& TREE_CODE (decl) != TYPE_DECL)
{
layout_decl (decl, 0);
if (pedantic && ! int_fits_type_p (value, integer_type_node))
{
- pedwarn ("ANSI C restricts enumerator values to range of `int'");
+ pedwarn ("ISO C restricts enumerator values to range of `int'");
value = convert (integer_type_node, value);
}
return tree_cons (decl, value, NULL_TREE);
}
+
\f
/* Create the FUNCTION_DECL for a function definition.
DECLSPECS, DECLARATOR, PREFIX_ATTRIBUTES and ATTRIBUTES are the parts of
else if (warn_missing_prototypes
&& TREE_PUBLIC (decl1)
&& !(old_decl != 0 && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0)
- && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))))
+ && ! MAIN_NAME_P (DECL_NAME (decl1)))
warning_with_decl (decl1, "no previous prototype for `%s'");
/* Optionally warn of any def with no previous prototype
if the function has already been used. */
&& old_decl != 0 && TREE_USED (old_decl)
&& TYPE_ARG_TYPES (TREE_TYPE (old_decl)) == 0)
warning_with_decl (decl1,
- "`%s' was used with no prototype before its definition");
+ "`%s' was used with no prototype before its definition");
/* Optionally warn of any global def with no previous declaration. */
else if (warn_missing_declarations
&& TREE_PUBLIC (decl1)
&& old_decl == 0
- && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))))
+ && ! MAIN_NAME_P (DECL_NAME (decl1)))
warning_with_decl (decl1, "no previous declaration for `%s'");
/* Optionally warn of any def with no previous declaration
if the function has already been used. */
&& old_decl != 0 && TREE_USED (old_decl)
&& old_decl == IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)))
warning_with_decl (decl1,
- "`%s' was used with no declaration before its definition");
+ "`%s' was used with no declaration before its definition");
/* This is a definition, not a reference.
So normally clear DECL_EXTERNAL.
#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;
if (current_function_decl != 0)
TREE_PUBLIC (decl1) = 0;
- /* Warn for unlikely, improbable, or stupid declarations of `main'. */
- if (warn_main > 0
- && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))) == 0)
+ /* Warn for unlikely, improbable, or stupid declarations of `main'. */
+ if (warn_main > 0 && MAIN_NAME_P (DECL_NAME (decl1)))
{
tree args;
int argct = 0;
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
- != integer_type_node)
+ != integer_type_node)
pedwarn_with_decl (decl1, "return type of `%s' is not `int'");
for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args;
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
!= char_type_node))
pedwarn_with_decl (decl1,
- "second argument of `%s' should be `char **'");
+ "second argument of `%s' should be `char **'");
break;
case 3:
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
!= char_type_node))
pedwarn_with_decl (decl1,
- "third argument of `%s' should probably be `char **'");
+ "third argument of `%s' should probably be `char **'");
break;
}
}
/* It is intentional that this message does not mention the third
argument, which is warned for only pedantically, because it's
- blessed by mention in an appendix of the standard. */
+ blessed by mention in an appendix of the standard. */
if (argct > 0 && (argct < 2 || argct > 3))
pedwarn_with_decl (decl1, "`%s' takes only zero or two arguments");
won't depend on its type. */
TREE_TYPE (dummy) = integer_type_node;
DECL_ARG_TYPE (dummy) = integer_type_node;
- DECL_ARGUMENTS (fndecl)
- = chainon (DECL_ARGUMENTS (fndecl), dummy);
+ DECL_ARGUMENTS (fndecl) = chainon (DECL_ARGUMENTS (fndecl), dummy);
}
#endif
DECL_ARG_TYPE (found) = TREE_TYPE (found);
DECL_SOURCE_LINE (found) = DECL_SOURCE_LINE (fndecl);
DECL_SOURCE_FILE (found) = DECL_SOURCE_FILE (fndecl);
- if (extra_warnings)
+ if (flag_isoc99)
+ pedwarn_with_decl (found, "type of `%s' defaults to `int'");
+ else if (extra_warnings)
warning_with_decl (found, "type of `%s' defaults to `int'");
pushdecl (found);
}
TREE_PURPOSE (parm) = found;
- /* Mark this decl as "already found" */
+ /* Mark this decl as "already found". */
DECL_WEAK (found) = 1;
}
any actual PARM_DECLs not matched with any names. */
nonparms = 0;
- for (parm = parmdecls; parm; )
+ for (parm = parmdecls; parm;)
{
tree next = TREE_CHAIN (parm);
TREE_CHAIN (parm) = 0;
{
/* 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;
- }
+ {
+ 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");
+ {
+ error_with_decl (parm,
+ "declaration for parameter `%s' but no such parameter");
/* Pretend the parameter was not missing.
This gets us to a standard state and minimizes
further error messages. */
- specparms
+ specparms
= chainon (specparms,
tree_cons (parm, NULL_TREE, NULL_TREE));
}
parm = next;
}
- /* Chain the declarations together in the order of the list of names. */
- /* Store that chain in the function decl, replacing the list of names. */
+ /* Chain the declarations together in the order of the list of
+ names. Store that chain in the function decl, replacing the
+ list of names. */
parm = specparms;
DECL_ARGUMENTS (fndecl) = 0;
{
init_function_start (fndecl, input_filename, lineno);
- /* If this is a varargs function, inform function.c. */
-
- if (c_function_varargs)
- mark_varargs ();
-
- /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
+ /* 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));
- declare_function_name ();
-
- /* Set up parameters and prepare for return, for the function. */
+ /* This function is being processed in whole-function mode. */
+ cfun->x_whole_function_mode_p = 1;
- expand_function_start (fndecl, 0);
-
- /* If this function is `main', emit a call to `__main'
- to run global initializers, etc. */
- if (DECL_NAME (fndecl)
- && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main") == 0
- && DECL_CONTEXT (fndecl) == NULL_TREE)
- expand_main_function ();
+ /* Even though we're inside a function body, we still don't want to
+ call expand_expr to calculate the size of a variable-sized array.
+ We haven't necessarily assigned RTL to all variables yet, so it's
+ not safe to try to expand expressions involving them. */
+ immediate_size_expand = 0;
+ cfun->x_dont_save_pending_sizes_p = 1;
}
\f
/* SPECPARMS is an identifier list--a chain of TREE_LIST nodes
/* Complain about any actual PARM_DECLs not matched with any names. */
- for (parm = parmdecls; parm; )
+ for (parm = parmdecls; parm;)
{
tree next = TREE_CHAIN (parm);
TREE_CHAIN (parm) = 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)));
setjmp_protect_args ();
}
- if (! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main"))
+ if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted)
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
!= integer_type_node)
{
/* If warn_main is 1 (-Wmain) or 2 (-Wall), we have already warned.
- If warn_main is -1 (-Wno-main) we don't want to be warned. */
+ If warn_main is -1 (-Wno-main) we don't want to be warned. */
if (! warn_main)
pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
}
#ifdef DEFAULT_MAIN_RETURN
/* Make it so that `main' always returns success by default. */
DEFAULT_MAIN_RETURN;
+#else
+ if (flag_isoc99)
+ c_expand_return (integer_zero_node);
#endif
}
}
+ /* Tie off the statement tree for this function. */
+ finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+ /* Clear out memory we no longer need. */
+ free_after_parsing (cfun);
+ /* Since we never call rest_of_compilation, we never clear
+ CFUN. Do so explicitly. */
+ free_after_compilation (cfun);
+ cfun = NULL;
+
+ if (! nested)
+ {
+ /* Generate RTL for the body of this function. */
+ c_expand_body (fndecl, nested);
+ /* Let the error reporting routines know that we're outside a
+ function. For a nested function, this value is used in
+ pop_c_function_context and then reset via pop_function_context. */
+ current_function_decl = NULL;
+ c_function_name_declared_p = 0;
+ }
+}
+
+/* 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. */
+
+static void
+c_expand_body (fndecl, nested_p)
+ tree fndecl;
+ int nested_p;
+{
+ /* 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 (nested_p)
+ push_function_context ();
+
+ /* Initialize the RTL code for the function. */
+ current_function_decl = fndecl;
+ init_function_start (fndecl, input_filename, DECL_SOURCE_LINE (fndecl));
+
+ /* This function is being processed in whole-function mode. */
+ cfun->x_whole_function_mode_p = 1;
+
+ /* Even though we're inside a function body, we still don't want to
+ call expand_expr to calculate the size of a variable-sized array.
+ We haven't necessarily assigned RTL to all variables yet, so it's
+ not safe to try to expand expressions involving them. */
+ immediate_size_expand = 0;
+ cfun->x_dont_save_pending_sizes_p = 1;
+
+ /* If this is a varargs function, inform function.c. */
+ if (c_function_varargs)
+ mark_varargs ();
+
+ /* Set up parameters and prepare for return, for the function. */
+ expand_function_start (fndecl, 0);
+
+ /* If this function is `main', emit a call to `__main'
+ to run global initializers, etc. */
+ if (DECL_NAME (fndecl)
+ && MAIN_NAME_P (DECL_NAME (fndecl))
+ && DECL_CONTEXT (fndecl) == NULL_TREE)
+ expand_main_function ();
+
+ /* Generate the RTL for this function. */
+ expand_stmt (DECL_SAVED_TREE (fndecl));
+ /* 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.
+ expand_function_end will decrement this variable. So, we set the
+ variable to one here, so that after the decrement it will remain
+ zero. */
+ immediate_size_expand = 1;
+
+ /* Allow language dialects to perform special processing. */
+ if (lang_expand_function_end)
+ (*lang_expand_function_end) ();
+
/* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 0);
- /* So we can tell if jump_optimize sets it to 1. */
- can_reach_end = 0;
-
/* If this is a nested function, protect the local variables in the stack
above us from being collected while we're compiling this function. */
- if (nested)
+ if (nested_p)
ggc_push_context ();
/* Run the optimizers and output the assembler code for this function. */
rest_of_compilation (fndecl);
/* Undo the GC context switch. */
- if (nested)
+ if (nested_p)
ggc_pop_context ();
- current_function_returns_null |= can_reach_end;
-
- if (warn_missing_noreturn
- && !TREE_THIS_VOLATILE (fndecl)
- && !current_function_returns_null
- && !current_function_returns_value)
- warning ("function might be possible candidate for attribute `noreturn'");
-
- if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
- warning ("`noreturn' function does return");
- else if (warn_return_type && can_reach_end
- && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
- /* If this function returns non-void and control can drop through,
- complain. */
- warning ("control reaches end of non-void function");
/* With just -W, complain only if function returns both with
and without a value. */
- else if (extra_warnings
- && current_function_returns_value && current_function_returns_null)
+ if (extra_warnings
+ && current_function_returns_value
+ && current_function_returns_null)
warning ("this function may return with or without a value");
/* If requested, warn about function definitions where the function will
size_as_int);
else
warning_with_decl (fndecl,
- "size of return value of `%s' is larger than %d bytes",
+ "size of return value of `%s' is larger than %d bytes",
larger_than_size);
}
}
- if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested)
+ if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested_p)
{
- /* Stop pointing to the local nodes about to be freed.
+ /* Stop pointing to the local nodes about to be freed.
But DECL_INITIAL must remain nonzero so we know this
- was an actual function definition.
+ was an actual function definition.
For a nested function, this is done in pop_c_function_context.
If rest_of_compilation set this to 0, leave it 0. */
if (DECL_INITIAL (fndecl) != 0)
static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
else
#endif
- assemble_constructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
+ assemble_constructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
}
if (DECL_STATIC_DESTRUCTOR (fndecl))
assemble_destructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
}
- if (! nested)
+ if (nested_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. */
- current_function_decl = NULL;
+ /* 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 ();
+ }
+ }
+
+}
+\f
+/* Check the declarations given in a for-loop for satisfying the C99
+ constraints. */
+void
+check_for_loop_decls ()
+{
+ tree t;
+
+ if (!flag_isoc99)
+ {
+ /* If we get here, declarations have been used in a for loop without
+ the C99 for loop scope. This doesn't make much sense, so don't
+ allow it. */
+ error ("`for' loop initial declaration used outside C99 mode");
+ return;
+ }
+ /* C99 subclause 6.8.5 paragraph 3:
+
+ [#3] The declaration part of a for statement shall only
+ declare identifiers for objects having storage class auto or
+ register.
+
+ It isn't clear whether, in this sentence, "identifiers" binds to
+ "shall only declare" or to "objects" - that is, whether all identifiers
+ declared must be identifiers for objects, or whether the restriction
+ only applies to those that are. (A question on this in comp.std.c
+ in November 2000 received no answer.) We implement the strictest
+ interpretation, to avoid creating an extension which later causes
+ problems. */
+
+ for (t = gettags (); t; t = TREE_CHAIN (t))
+ {
+ if (TREE_PURPOSE (t) != 0)
+ 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)));
+ }
+ for (t = getdecls (); t; t = TREE_CHAIN (t))
+ {
+ if (TREE_CODE (t) != VAR_DECL && DECL_NAME (t))
+ error_with_decl (t, "declaration of non-variable `%s' in `for' loop initial declaration");
+ else if (TREE_STATIC (t))
+ error_with_decl (t, "declaration of static variable `%s' in `for' loop initial declaration");
+ else if (DECL_EXTERNAL (t))
+ error_with_decl (t, "declaration of `extern' variable `%s' in `for' loop initial declaration");
}
}
\f
that keep track of the progress of compilation of the current function.
Used for nested functions. */
-struct language_function
+struct c_language_function
{
+ struct language_function base;
tree named_labels;
tree shadowed_labels;
int returns_value;
push_c_function_context (f)
struct function *f;
{
- struct language_function *p;
- p = (struct language_function *) xmalloc (sizeof (struct language_function));
- f->language = p;
-
+ struct c_language_function *p;
+ p = ((struct c_language_function *)
+ xmalloc (sizeof (struct c_language_function)));
+ f->language = (struct language_function *) p;
+
+ p->base.x_stmt_tree = c_stmt_tree;
+ p->base.x_scope_stmt_stack = c_scope_stmt_stack;
+ p->base.x_function_name_declared_p = c_function_name_declared_p;
p->named_labels = named_labels;
p->shadowed_labels = shadowed_labels;
p->returns_value = current_function_returns_value;
pop_c_function_context (f)
struct function *f;
{
- struct language_function *p = f->language;
+ struct c_language_function *p
+ = (struct c_language_function *) f->language;
tree link;
/* Bring back all the labels that were shadowed. */
IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
= TREE_VALUE (link);
- if (DECL_SAVED_INSNS (current_function_decl) == 0)
+ if (DECL_SAVED_INSNS (current_function_decl) == 0
+ && DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
{
/* Stop pointing to the local nodes about to be freed. */
/* But DECL_INITIAL must remain nonzero so we know this
DECL_ARGUMENTS (current_function_decl) = 0;
}
+ c_stmt_tree = p->base.x_stmt_tree;
+ c_scope_stmt_stack = p->base.x_scope_stmt_stack;
+ c_function_name_declared_p = p->base.x_function_name_declared_p;
named_labels = p->named_labels;
shadowed_labels = p->shadowed_labels;
current_function_returns_value = p->returns_value;
}
/* Mark the language specific parts of F for GC. */
+
void
mark_c_function_context (f)
struct function *f;
{
- struct language_function *p = f->language;
+ struct c_language_function *p
+ = (struct c_language_function *) f->language;
if (p == 0)
return;
+ mark_c_language_function (&p->base);
ggc_mark_tree (p->shadowed_labels);
ggc_mark_tree (p->named_labels);
mark_binding_level (&p->binding_level);
}
-/* integrate_decl_tree calls this function, but since we don't use the
- DECL_LANG_SPECIFIC field, this is a no-op. */
+/* Copy the DECL_LANG_SEPECIFIC data associated with NODE. */
void
-copy_lang_decl (node)
- tree node ATTRIBUTE_UNUSED;
+copy_lang_decl (decl)
+ tree decl;
{
-}
+ struct lang_decl *ld;
-/* Mark ARG for GC. */
-void
-lang_mark_false_label_stack (arg)
- struct label_node *arg;
-{
- /* C doesn't use false_label_stack. It better be NULL. */
- if (arg != NULL)
- abort();
+ if (!DECL_LANG_SPECIFIC (decl))
+ return;
+
+ ld = (struct lang_decl *) ggc_alloc (sizeof (struct lang_decl));
+ memcpy ((char *) ld, (char *) DECL_LANG_SPECIFIC (decl),
+ sizeof (struct lang_decl));
+ DECL_LANG_SPECIFIC (decl) = ld;
}
/* Mark the language specific bits in T for GC. */
+
void
lang_mark_tree (t)
tree t;
}
else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
ggc_mark (TYPE_LANG_SPECIFIC (t));
+ else if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
+ {
+ ggc_mark (DECL_LANG_SPECIFIC (t));
+ c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base);
+ }
}
/* The functions below are required for functionality of doing
function at once processing in the C front end. Currently these
functions are not called from anywhere in the C front end, but as
- these changes continue, that will change. */
+ these changes continue, that will change. */
/* Returns non-zero if the current statement is a full expression,
i.e. temporaries created during that statement should be destroyed
return 0;
}
-/* Nonzero if TYPE is an anonymous union or struct type. Always 0 in
- C. */
+/* Returns the stmt_tree (if any) to which statements are currently
+ being added. If there is no active statement-tree, NULL is
+ returned. */
-int
-anon_aggr_type_p (node)
- tree node ATTRIBUTE_UNUSED;
+stmt_tree
+current_stmt_tree ()
{
- return 0;
+ return &c_stmt_tree;
+}
+
+/* Returns the stack of SCOPE_STMTs for the current function. */
+
+tree *
+current_scope_stmt_stack ()
+{
+ return &c_scope_stmt_stack;
}
-/* One if we have already declared __FUNCTION__ (and related
- variables) in the current function. Two if we are in the process
- of doing so. */
+/* Nonzero if TYPE is an anonymous union or struct type. Always 0 in
+ C. */
int
-current_function_name_declared ()
+anon_aggr_type_p (node)
+ tree node ATTRIBUTE_UNUSED;
{
- abort ();
return 0;
}
-/* Code to generate the RTL for a case label in C. */
+/* Dummy function in place of callback used by C++. */
void
-do_case (low_value, high_value)
- tree low_value;
- tree high_value;
+extract_interface_info ()
{
- tree value1 = NULL_TREE, value2 = NULL_TREE, label;
-
- if (low_value != NULL_TREE)
- value1 = check_case_value (low_value);
- if (high_value != NULL_TREE)
- value2 = check_case_value (high_value);
-
- label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
- if (pedantic && (high_value != NULL_TREE))
- pedwarn ("ANSI C forbids case ranges");
-
- if (value1 != error_mark_node && value2 != error_mark_node)
- {
- tree duplicate;
- int success;
-
- if (high_value == NULL_TREE && value1 != NULL_TREE &&
- pedantic && ! INTEGRAL_TYPE_P (TREE_TYPE (value1)))
- pedwarn ("label must have integral type in ANSI C");
-
- if (low_value == NULL_TREE)
- success = pushcase (NULL_TREE, 0, label, &duplicate);
- else if (high_value == NULL_TREE)
- success = pushcase (value1, convert_and_check, label,
- &duplicate);
- else
- success = pushcase_range (value1, value2, convert_and_check,
- label, &duplicate);
-
- if (success == 1)
- {
- if (low_value == NULL_TREE)
- error ("default label not within a switch statement");
- else
- error ("case label not within a switch statement");
- }
- else if (success == 2) {
- if (low_value == NULL_TREE)
- {
- error ("multiple default labels in one switch");
- error_with_decl (duplicate, "this is the first default label");
- }
- else
- error ("dupicate case value");
- if (high_value != NULL_TREE)
- error_with_decl (duplicate, "this is the first entry for that value");
- }
- else if (low_value != NULL_TREE)
- {
- if (success == 3)
- warning ("case value out of range");
- else if (success == 5)
- error ("case label within scope of cleanup or variable array");
- }
- }
}
-/* Language specific handler of tree nodes used when generating RTL
- from a tree. */
+/* Return a new COMPOUND_STMT, after adding it to the current
+ statement tree. */
tree
-lang_expand_stmt (t)
- tree t ATTRIBUTE_UNUSED;
+c_begin_compound_stmt ()
{
- abort ();
- return NULL_TREE;
+ tree stmt;
+
+ /* Create the COMPOUND_STMT. */
+ stmt = add_stmt (build_stmt (COMPOUND_STMT, NULL_TREE));
+ /* If we haven't already declared __FUNCTION__ and its ilk then this
+ is the opening curly brace of the function. Declare them now. */
+ if (!c_function_name_declared_p)
+ {
+ c_function_name_declared_p = 1;
+ declare_function_name ();
+ }
+
+ return stmt;
}
-/* Accessor to set the 'current_function_name_declared' flag. */
+/* Expand T (a DECL_STMT) if it declares an entity not handled by the
+ common code. */
void
-set_current_function_name_declared (i)
- int i ATTRIBUTE_UNUSED;
+c_expand_decl_stmt (t)
+ tree t;
{
- abort ();
+ tree decl = DECL_STMT_DECL (t);
+
+ /* Expand nested functions. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_CONTEXT (decl) == current_function_decl
+ && DECL_SAVED_TREE (decl))
+ c_expand_body (decl, /*nested_p=*/1);
}
-