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 WINT_TYPE
#define WINT_TYPE "unsigned int"
#endif
-\f
-/* Do GC. */
-int ggc_p = 1;
+#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 = -1;
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.
implicit_decl_warning (id)
tree id;
{
- char *name = IDENTIFIER_POINTER (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)
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)));
+ 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);
}
+ }
+ else if (decl_context == FIELD)
+ {
+ /* ??? Need to check somewhere that this is a structure
+ and not a union, that this field is last, and that
+ this structure has at least one other named member. */
+
+ if (pedantic && !flag_isoc99 && !in_system_header)
+ pedwarn ("ISO C89 does not support flexible array members");
- if (size_varies)
- itype = variable_size (itype);
- itype = build_index_type (itype);
+ /* 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]; */
+#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.
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).
- */
+ 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))
/* 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
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. */
+ /* 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 (c_function_varargs)
- mark_varargs ();
+ /* This function is being processed in whole-function mode. */
+ cfun->x_whole_function_mode_p = 1;
- /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
-
- declare_function_name ();
-
- /* Set up parameters and prepare for return, for the function. */
-
- expand_function_start (fndecl, 0);
-
- /* If this function is `main', emit a call to `__main'
- to run global initializers, etc. */
- if (DECL_NAME (fndecl)
- && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main") == 0
- && DECL_CONTEXT (fndecl) == NULL_TREE)
- expand_main_function ();
+ /* 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")
- && flag_hosted)
+ 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'");
}
}
}
+ /* 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;
}
-/* One if we have already declared __FUNCTION__ (and related
- variables) in the current function. Two if we are in the process
- of doing so. */
+/* Returns the stack of SCOPE_STMTs for the current function. */
+
+tree *
+current_scope_stmt_stack ()
+{
+ return &c_scope_stmt_stack;
+}
+
+/* Nonzero if TYPE is an anonymous union or struct type. Always 0 in
+ C. */
int
-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);
}
-