#include "timevar.h"
#include "c-common.h"
#include "c-pragma.h"
+#include "langhooks.h"
+#include "tree-mudflap.h"
+#include "tree-gimple.h"
+#include "diagnostic.h"
+#include "tree-dump.h"
#include "cgraph.h"
#include "hashtab.h"
#include "libfuncs.h"
\f
/* Nonzero if we have seen an invalid cross reference
to a struct, union, or enum, but not yet printed the message. */
-
tree pending_invalid_xref;
+
/* File and line to appear in the eventual error message. */
location_t pending_invalid_xref_location;
+/* True means we've initialized exception handling. */
+bool c_eh_initialized_p;
+
/* While defining an enum type, this is 1 plus the last enumerator
constant value. Note that will do not have to save this or `enum_overflow'
around nested function definition since such a definition could only
static GTY(()) struct stmt_tree_s c_stmt_tree;
-/* The current scope statement stack. */
-
-static GTY(()) tree c_scope_stmt_stack;
-
/* State saving variables. */
-int c_in_iteration_stmt;
-int c_in_case_stmt;
+tree c_break_label;
+tree c_cont_label;
-/* A DECL for the current file-scope context. */
+/* Linked list of TRANSLATION_UNIT_DECLS for the translation units
+ included in this invocation. Note that the current translation
+ unit is not included in this list. */
-static GTY(()) tree current_file_decl;
+static GTY(()) tree all_translation_units;
/* A list of decls to be made automatically visible in each file scope. */
static GTY(()) tree visible_builtins;
suppress further errors about that identifier in the current
function. */
-struct c_binding GTY(())
+struct c_binding GTY((chain_next ("%h.prev")))
{
tree decl; /* the decl bound */
tree id; /* the identifier it's bound to */
#define I_LABEL_DECL(node) \
(I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0)
+/* Each C symbol points to three linked lists of c_binding structures.
+ These describe the values of the identifier in the three different
+ namespaces defined by the language. */
+
+struct lang_identifier GTY(())
+{
+ struct c_common_identifier common_id;
+ struct c_binding *symbol_binding; /* vars, funcs, constants, typedefs */
+ struct c_binding *tag_binding; /* struct/union/enum tags */
+ struct c_binding *label_binding; /* labels */
+};
+
+/* Validate c-lang.c's assumptions. */
+extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
+[(sizeof(struct lang_identifier) == C_SIZEOF_STRUCT_LANG_IDENTIFIER) ? 1 : -1];
+
+/* The resulting tree type. */
+
+union lang_tree_node
+ GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
+ chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *)TYPE_NEXT_VARIANT (&%h.generic) : (union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
+{
+ union tree_node GTY ((tag ("0"),
+ desc ("tree_node_structure (&%h)")))
+ generic;
+ struct lang_identifier GTY ((tag ("1"))) identifier;
+};
+
/* Each c_scope structure describes the complete contents of one
scope. Four scopes are distinguished specially: the innermost or
current scope, the innermost function scope, the file scope (always
pop_scope relies on this. */
-struct c_scope GTY(())
+struct c_scope GTY((chain_next ("%h.outer")))
{
/* The scope containing this one. */
struct c_scope *outer;
/* A chain of c_scope structures awaiting reuse. */
-static GTY((deletable (""))) struct c_scope *scope_freelist;
+static GTY((deletable)) struct c_scope *scope_freelist;
/* A chain of c_binding structures awaiting reuse. */
-static GTY((deletable (""))) struct c_binding *binding_freelist;
+static GTY((deletable)) struct c_binding *binding_freelist;
/* Append VAR to LIST in scope SCOPE. */
#define SCOPE_LIST_APPEND(scope, list, decl) do { \
if (TREE_CODE (b->decl) == VAR_DECL
|| TREE_CODE (b->decl) == PARM_DECL)
{
+ C_DECL_REGISTER (b->decl) = 0;
DECL_REGISTER (b->decl) = 0;
TREE_THIS_VOLATILE (b->decl) = 1;
}
scope->depth--;
sorry ("GCC supports only %u nested scopes\n", scope->depth);
}
-
+
current_scope = scope;
keep_next_level_flag = false;
}
if (scope->function_body)
context = current_function_decl;
else if (scope == file_scope)
- context = current_file_decl;
+ {
+ tree file_decl = build_decl (TRANSLATION_UNIT_DECL, 0, 0);
+ TREE_CHAIN (file_decl) = all_translation_units;
+ all_translation_units = file_decl;
+ context = file_decl;
+ }
else
context = block;
/* Labels go in BLOCK_VARS. */
TREE_CHAIN (p) = BLOCK_VARS (block);
BLOCK_VARS (block) = p;
-
+
#ifdef ENABLE_CHECKING
if (I_LABEL_BINDING (b->id) != b) abort ();
#endif
TREE_CHAIN (p) = BLOCK_VARS (block);
BLOCK_VARS (block) = p;
}
+ /* If this is the file scope, must set DECL_CONTEXT on these. */
+ if (!C_DECL_IN_EXTERNAL_SCOPE (p) && scope == file_scope)
+ DECL_CONTEXT (p) = context;
/* Fall through. */
/* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
}
}
-
+
/* Dispose of the block that we just made inside some higher level. */
if ((scope->function_body || scope == file_scope) && context)
{
push_file_scope (void)
{
tree decl;
- tree file_decl = build_decl (TRANSLATION_UNIT_DECL, 0, 0);
- TREE_CHAIN (file_decl) = current_file_decl;
- current_file_decl = file_decl;
+
+ if (file_scope)
+ return;
push_scope ();
file_scope = current_scope;
tree t;
if (TREE_CODE (olddecl) != FUNCTION_DECL
- || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype), COMPARE_STRICT)
+ || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype))
|| !((TYPE_ARG_TYPES (oldtype) == 0 && DECL_INITIAL (olddecl) == 0)
||
(TYPE_ARG_TYPES (newtype) == 0 && DECL_INITIAL (newdecl) == 0)))
/* Type for passing arg must be consistent with that declared
for the arg. */
- else if (! comptypes (oldargtype, newargtype, COMPARE_STRICT))
+ else if (! comptypes (oldargtype, newargtype))
{
error ("%Jprototype for '%D' declares arg %d with incompatible type",
newdecl, newdecl, i);
return false;
}
- if (!comptypes (oldtype, newtype, COMPARE_STRICT))
+ if (!comptypes (oldtype, newtype))
{
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_BUILT_IN (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl))
This is for the ffs and fprintf builtins. */
tree trytype = match_builtin_function_types (newtype, oldtype);
- if (trytype && comptypes (newtype, trytype, COMPARE_STRICT))
+ if (trytype && comptypes (newtype, trytype))
*oldtypep = oldtype = trytype;
else
{
}
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_SOURCE_LINE (olddecl) == 0)
+ && DECL_IS_BUILTIN (olddecl))
{
/* A conflicting function declaration for a predeclared
function that isn't actually built in. Objective C uses
}
else
{
- error ("%Jconflicting types for '%D'", newdecl, newdecl);
+ if (TYPE_QUALS (newtype) != TYPE_QUALS (oldtype))
+ error ("%J conflicting type qualifiers for '%D'", newdecl, newdecl);
+ else
+ error ("%Jconflicting types for '%D'", newdecl, newdecl);
diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
locate_old_decl (olddecl, error);
return false;
{
if (DECL_IN_SYSTEM_HEADER (newdecl) || DECL_IN_SYSTEM_HEADER (olddecl))
return true; /* Allow OLDDECL to continue in use. */
-
+
error ("%Jredefinition of typedef '%D'", newdecl, newdecl);
locate_old_decl (olddecl, error);
return false;
/* Discard the old built-in function. */
return false;
}
-
+
if (DECL_INITIAL (newdecl))
{
if (DECL_INITIAL (olddecl)
default. Objective C uses these. See also above.
FIXME: Make Objective C use normal builtins. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_SOURCE_LINE (olddecl) == 0)
+ && DECL_IS_BUILTIN (olddecl))
return false;
else
{
locate_old_decl (olddecl, error);
return false;
}
-
- /* These bits are only type qualifiers when applied to objects. */
- if (TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))
- {
- if (TREE_THIS_VOLATILE (newdecl))
- pedwarn ("%Jvolatile declaration of '%D' follows "
- "non-volatile declaration", newdecl, newdecl);
- else
- pedwarn ("%Jnon-volatile declaration of '%D' follows "
- "volatile declaration", newdecl, newdecl);
- pedwarned = true;
- }
- if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl))
- {
- if (TREE_READONLY (newdecl))
- pedwarn ("%Jconst declaration of '%D' follows "
- "non-const declaration", newdecl, newdecl);
- else
- pedwarn ("%Jnon-const declaration of '%D' follows "
- "const declaration", newdecl, newdecl);
- pedwarned = true;
- }
}
/* Optional warning for completely redundant decls. */
/* Merge the data types specified in the two decls. */
TREE_TYPE (newdecl)
= TREE_TYPE (olddecl)
- = common_type (newtype, oldtype);
+ = composite_type (newtype, oldtype);
/* Lay the type out, unless already done. */
if (oldtype != TREE_TYPE (newdecl))
static bool
duplicate_decls (tree newdecl, tree olddecl)
{
- tree newtype, oldtype;
+ tree newtype = NULL, oldtype = NULL;
if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
return false;
merge_decls (newdecl, olddecl, newtype, oldtype);
return true;
}
-
+
\f
/* Check whether decl-node NEW shadows an existing declaration. */
static void
/* Shadow warnings wanted? */
if (!warn_shadow
/* No shadow warnings for internally generated vars. */
- || DECL_SOURCE_LINE (new) == 0
+ || DECL_IS_BUILTIN (new)
/* No shadow warnings for vars made for inlining. */
|| DECL_FROM_INLINE (new)
/* Don't warn about the parm names in function declarator
static void
clone_underlying_type (tree x)
{
- if (DECL_SOURCE_LINE (x) == 0)
+ if (DECL_IS_BUILTIN (x))
{
if (TYPE_NAME (TREE_TYPE (x)) == 0)
TYPE_NAME (TREE_TYPE (x)) = x;
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
DECL_LANG_SPECIFIC (x) = ggc_alloc_cleared (sizeof (struct lang_decl));
- /* A local extern declaration for a function doesn't constitute nesting.
- A local auto declaration does, since it's a forward decl
- for a nested function coming later. */
- if (current_function_decl == NULL
- || ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
- && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x)))
- DECL_CONTEXT (x) = current_file_decl;
- else
+ /* Must set DECL_CONTEXT for everything not at file scope or
+ DECL_FILE_SCOPE_P won't work. Local externs don't count
+ unless they have initializers (which generate code). */
+ if (current_function_decl
+ && ((TREE_CODE (x) != FUNCTION_DECL && TREE_CODE (x) != VAR_DECL)
+ || DECL_INITIAL (x) || !DECL_EXTERNAL (x)))
DECL_CONTEXT (x) = current_function_decl;
/* Anonymous decls are just inserted in the scope. */
if (I_SYMBOL_BINDING (name))
abort ();
- DECL_CONTEXT (x) = current_file_decl;
if (DECL_EXTERNAL (x) || TREE_PUBLIC (x))
{
C_DECL_IN_EXTERNAL_SCOPE (x) = 1;
in the external scope because they're pushed before the file
scope gets created. Catch this here and rebind them into the
file scope. */
- if (!DECL_BUILT_IN (decl) && DECL_SOURCE_LINE (decl) == 0)
+ if (!DECL_BUILT_IN (decl) && DECL_IS_BUILTIN (decl))
{
bind (functionid, decl, file_scope);
return decl;
any that may be inherited from containing functions or containing
scopes. This is called for __label__ declarations. */
-/* Note that valid use, if the label being shadowed comes from another
- scope in the same function, requires calling declare_nonlocal_label
- right away. (Is this still true? -zw 2003-07-17) */
-
tree
declare_label (tree name)
{
/* For our purposes, a tag in the external scope is the same as
a tag in the file scope. (Primarily relevant to Objective-C
and its builtin structure tags, which get pushed before the
- file scope is created.) */
+ file scope is created.) */
if (b->contour == current_scope
|| (current_scope == file_scope && b->contour == external_scope))
thislevel = 1;
/* Declarations from c_common_nodes_and_builtins must not be associated
with this input file, lest we get differences between using and not
using preprocessed headers. */
- input_location.file = "<internal>";
+#ifdef USE_MAPPED_LOCATION
+ input_location = BUILTINS_LOCATION;
+#else
+ input_location.file = "<built-in>";
input_location.line = 0;
+#endif
build_common_tree_nodes (flag_signed_char);
DECL_ARTIFICIAL (decl) = 1;
init = build_string (length + 1, name);
+ free ((char *) name);
TREE_TYPE (init) = type;
DECL_INITIAL (decl) = init;
DECL_FUNCTION_CODE (decl) = function_code;
if (library_name)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
- make_decl_rtl (decl, NULL);
/* Should never be called on a symbol with a preexisting meaning. */
if (I_SYMBOL_BINDING (id))
build_array_declarator (tree expr, tree quals, int static_p, int vla_unspec_p)
{
tree decl;
- decl = build_nt (ARRAY_REF, NULL_TREE, expr);
+ decl = build_nt (ARRAY_REF, NULL_TREE, expr, NULL_TREE, NULL_TREE);
TREE_TYPE (decl) = quals;
TREE_STATIC (decl) = (static_p ? 1 : 0);
if (pedantic && !flag_isoc99)
for (; args; args = TREE_CHAIN (args))
{
tree type = TREE_TYPE (args);
- if (INTEGRAL_TYPE_P (type)
+ if (type && INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (args) = integer_type_node;
}
{
tree builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
SET_DECL_RTL (builtin, NULL_RTX);
- SET_DECL_ASSEMBLER_NAME (builtin, get_identifier (starred));
+ change_decl_assembler_name (builtin, get_identifier (starred));
#ifdef TARGET_MEM_FUNCTIONS
if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
init_block_move_fn (starred);
/* In conjunction with an ASMSPEC, the `register'
keyword indicates that we should place the variable
in a particular register. */
- if (DECL_REGISTER (decl))
- DECL_C_HARD_REGISTER (decl) = 1;
+ if (C_DECL_REGISTER (decl))
+ {
+ DECL_HARD_REGISTER (decl) = 1;
+ /* This cannot be done for a structure with volatile
+ fields, on which DECL_REGISTER will have been
+ reset. */
+ if (!DECL_REGISTER (decl))
+ error ("cannot put object with volatile field into register");
+ }
/* If this is not a static variable, issue a warning.
It doesn't make any sense to give an ASMSPEC for an
GCC has accepted -- but ignored -- the ASMSPEC in
this case. */
if (TREE_CODE (decl) == VAR_DECL
- && !DECL_REGISTER (decl)
+ && !C_DECL_REGISTER (decl)
&& !TREE_STATIC (decl))
warning ("%Jignoring asm-specifier for non-static local "
"variable '%D'", decl, decl);
}
if (TREE_CODE (decl) != FUNCTION_DECL)
- add_decl_stmt (decl);
+ add_stmt (build_stmt (DECL_EXPR, decl));
}
if (!DECL_FILE_SCOPE_P (decl))
/* If this was marked 'used', be sure it will be output. */
if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
- mark_referenced (DECL_ASSEMBLER_NAME (decl));
+ mark_decl_referenced (decl);
if (TREE_CODE (decl) == TYPE_DECL)
- rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0);
+ {
+ if (!DECL_FILE_SCOPE_P (decl)
+ && variably_modified_type_p (TREE_TYPE (decl)))
+ add_stmt (build_stmt (DECL_EXPR, decl));
+
+ rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0);
+ }
/* At the end of a declaration, throw away any variable type sizes
of types defined inside that declaration. There is no use
tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
if (attr)
{
- static bool eh_initialized_p;
-
tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
tree cleanup_decl = lookup_name (cleanup_id);
tree cleanup;
/* Don't warn about decl unused; the cleanup uses it. */
TREE_USED (decl) = 1;
+ TREE_USED (cleanup_decl) = 1;
/* Initialize EH, if we've been told to do so. */
- if (flag_exceptions && !eh_initialized_p)
+ if (flag_exceptions && !c_eh_initialized_p)
{
- eh_initialized_p = true;
+ c_eh_initialized_p = true;
eh_personality_libfunc
= init_one_libfunc (USING_SJLJ_EXCEPTIONS
? "__gcc_personality_sj0"
using_eh_for_cleanups ();
}
- add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
+ push_cleanup (decl, cleanup, false);
}
}
}
{
tree decl;
- /* Don't attempt to expand sizes while parsing this decl.
- (We can get here with i_s_e 1 somehow from Objective-C.) */
- int save_immediate_size_expand = immediate_size_expand;
- immediate_size_expand = 0;
-
decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
TREE_PURPOSE (TREE_PURPOSE (parm)),
PARM, 0, NULL);
decl = pushdecl (decl);
finish_decl (decl, NULL_TREE, NULL_TREE);
-
- immediate_size_expand = save_immediate_size_expand;
}
/* Mark all the parameter declarations to date as forward decls.
{
/* We do not use start_decl here because we have a type, not a declarator;
and do not use finish_decl because the decl should be stored inside
- the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_STMT. */
+ the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_EXPR. */
tree decl = build_decl (VAR_DECL, NULL_TREE, type);
tree complit;
tree stmt;
DECL_CONTEXT (decl) = current_function_decl;
TREE_USED (decl) = 1;
TREE_TYPE (decl) = type;
- TREE_READONLY (decl) = TREE_READONLY (type);
+ TREE_READONLY (decl) = TYPE_READONLY (type);
store_init_value (decl, init);
if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
return error_mark_node;
- stmt = build_stmt (DECL_STMT, decl);
+ stmt = build_stmt (DECL_EXPR, decl);
complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
TREE_SIDE_EFFECTS (complit) = 1;
else
w = tree_low_cst (*width, 1);
- if (TREE_CODE (*type) == ENUMERAL_TYPE
- && (w < min_precision (TYPE_MIN_VALUE (*type), TREE_UNSIGNED (*type))
- || w < min_precision (TYPE_MAX_VALUE (*type), TREE_UNSIGNED (*type))))
- warning ("`%s' is narrower than values of its type", name);
+ if (TREE_CODE (*type) == ENUMERAL_TYPE)
+ {
+ struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
+ if (!lt
+ || w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
+ || w < min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
+ warning ("`%s' is narrower than values of its type", name);
+ }
}
\f
/* Given declspecs and a declarator,
type = error_mark_node;
}
- if (pedantic && flexible_array_type_p (type))
+ if (pedantic && !in_system_header && flexible_array_type_p (type))
pedwarn ("invalid use of structure with flexible array member");
if (size == error_mark_node)
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
}
+ else if (declarator && TREE_CODE (declarator) == INDIRECT_REF)
+ /* We can never complete an array type which is the target of a
+ pointer, so go ahead and lay it out. */
+ layout_type (type);
+
if (decl_context != PARM
&& (array_ptr_quals != NULL_TREE || array_parm_static))
{
and in case doing stupid register allocation. */
if (specbits & (1 << (int) RID_REGISTER))
- DECL_REGISTER (decl) = 1;
+ {
+ C_DECL_REGISTER (decl) = 1;
+ DECL_REGISTER (decl) = 1;
+ }
/* Record constancy and volatility. */
c_apply_type_quals_to_decl (type_quals, decl);
Otherwise, the fact that those components are volatile
will be ignored, and would even crash the compiler. */
if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
- c_mark_addressable (decl);
+ {
+ /* It is not an error for a structure with volatile fields to
+ be declared register, but reset DECL_REGISTER since it
+ cannot actually go in a register. */
+ int was_reg = C_DECL_REGISTER (decl);
+ C_DECL_REGISTER (decl) = 0;
+ DECL_REGISTER (decl) = 0;
+ c_mark_addressable (decl);
+ C_DECL_REGISTER (decl) = was_reg;
+ }
#ifdef ENABLE_CHECKING
/* This is the earliest point at which we might know the assembler
{
if (TREE_THIS_VOLATILE (b->decl)
|| TREE_READONLY (b->decl)
- || DECL_REGISTER (b->decl))
+ || C_DECL_REGISTER (b->decl))
error ("'void' as only parameter may not be qualified");
/* There cannot be an ellipsis. */
}
break;
- case ENUMERAL_TYPE: keyword = "struct"; goto tag;
+ case ENUMERAL_TYPE: keyword = "enum"; goto tag;
case UNION_TYPE: keyword = "union"; goto tag;
- case RECORD_TYPE: keyword = "enum"; goto tag;
+ case RECORD_TYPE: keyword = "struct"; goto tag;
tag:
/* Types may not have tag-names, in which case the type
appears in the bindings list with b->id NULL. */
/* The %s will be one of 'struct', 'union', or 'enum'. */
warning ("anonymous %s declared inside parameter list",
keyword);
-
+
if (! explained_incomplete_types)
{
warning ("its scope is only this definition or declaration,"
and TYPE_DECLs appear here when we have an embedded struct
or union. No warnings for this - we already warned about the
type itself. */
+ TREE_CHAIN (decl) = others;
+ others = decl;
+ /* fall through */
+
+ case ERROR_MARK:
+ /* error_mark_node appears here when we have an undeclared
+ variable. Just throw it away. */
if (b->id)
{
#ifdef ENABLE_CHECKING
#endif
I_SYMBOL_BINDING (b->id) = b->shadowed;
}
-
- TREE_CHAIN (decl) = others;
- others = decl;
break;
/* Other things that might be encountered. */
case LABEL_DECL:
case FUNCTION_DECL:
case VAR_DECL:
- case ERROR_MARK:
default:
abort ();
}
TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
TYPE_USER_ALIGN (ref) = 0;
- TREE_UNSIGNED (ref) = 1;
+ TYPE_UNSIGNED (ref) = 1;
TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
}
}
- if (pedantic && TREE_CODE (t) == RECORD_TYPE
+ if (pedantic && !in_system_header && TREE_CODE (t) == RECORD_TYPE
&& flexible_array_type_p (TREE_TYPE (x)))
pedwarn ("%Jinvalid use of structure with flexible array member", x);
ensure that this lives as long as the rest of the struct decl.
All decls in an inline function need to be saved. */
- space = ggc_alloc (sizeof (struct lang_type));
+ space = ggc_alloc_cleared (sizeof (struct lang_type));
space2 = ggc_alloc (sizeof (struct sorted_fields_type) + len * sizeof (tree));
len = 0;
finish_enum (tree enumtype, tree values, tree attributes)
{
tree pair, tem;
- tree minnode = 0, maxnode = 0, enum_value_type;
+ tree minnode = 0, maxnode = 0;
int precision, unsign;
bool toplevel = (file_scope == current_scope);
+ struct lang_type *lt;
decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
min_precision (maxnode, unsign));
if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
{
- tree narrowest = c_common_type_for_size (precision, unsign);
- if (narrowest == 0)
+ tem = c_common_type_for_size (precision, unsign);
+ if (tem == NULL)
{
warning ("enumeration values exceed range of largest integer");
- narrowest = long_long_integer_type_node;
+ tem = long_long_integer_type_node;
}
-
- precision = TYPE_PRECISION (narrowest);
}
else
- precision = TYPE_PRECISION (integer_type_node);
-
- if (precision == TYPE_PRECISION (integer_type_node))
- enum_value_type = c_common_type_for_size (precision, 0);
- else
- enum_value_type = enumtype;
+ tem = unsign ? unsigned_type_node : integer_type_node;
- TYPE_MIN_VALUE (enumtype) = minnode;
- TYPE_MAX_VALUE (enumtype) = maxnode;
- TYPE_PRECISION (enumtype) = precision;
- TREE_UNSIGNED (enumtype) = unsign;
+ TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem);
+ TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem);
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem);
+ TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem);
TYPE_SIZE (enumtype) = 0;
layout_type (enumtype);
for (pair = values; pair; pair = TREE_CHAIN (pair))
{
tree enu = TREE_PURPOSE (pair);
+ tree ini = DECL_INITIAL (enu);
TREE_TYPE (enu) = enumtype;
when comparing integers with enumerators that fit in the
int range. When -pedantic is given, build_enumerator()
would have already taken care of those that don't fit. */
- if (int_fits_type_p (DECL_INITIAL (enu), enum_value_type))
- DECL_INITIAL (enu) = convert (enum_value_type, DECL_INITIAL (enu));
+ if (int_fits_type_p (ini, integer_type_node))
+ tem = integer_type_node;
else
- DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu));
+ tem = enumtype;
+ ini = convert (tem, ini);
+ DECL_INITIAL (enu) = ini;
TREE_PURPOSE (pair) = DECL_NAME (enu);
- TREE_VALUE (pair) = DECL_INITIAL (enu);
+ TREE_VALUE (pair) = ini;
}
TYPE_VALUES (enumtype) = values;
}
+ /* Record the min/max values so that we can warn about bit-field
+ enumerations that are too small for the values. */
+ lt = ggc_alloc_cleared (sizeof (struct lang_type));
+ lt->enum_min = minnode;
+ lt->enum_max = maxnode;
+ TYPE_LANG_SPECIFIC (enumtype) = lt;
+
/* Fix up all variant types of this enum type. */
for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
{
TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
- TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
+ TYPE_UNSIGNED (tem) = TYPE_UNSIGNED (enumtype);
+ TYPE_LANG_SPECIFIC (tem) = TYPE_LANG_SPECIFIC (enumtype);
}
/* Finish debugging output for this type. */
TYPE_PRECISION (integer_type_node)),
(TYPE_PRECISION (type)
>= TYPE_PRECISION (integer_type_node)
- && TREE_UNSIGNED (type)));
+ && TYPE_UNSIGNED (type)));
decl = build_decl (CONST_DECL, name, type);
DECL_INITIAL (decl) = convert (type, value);
{
tree decl1, old_decl;
tree restype;
- int old_immediate_size_expand = immediate_size_expand;
current_function_returns_value = 0; /* Assume, until we see it does. */
current_function_returns_null = 0;
current_function_returns_abnormally = 0;
warn_about_return_type = 0;
current_extern_inline = 0;
- c_in_iteration_stmt = 0;
- c_in_case_stmt = 0;
+ c_switch_stack = NULL;
- /* Don't expand any sizes in the return type of the function. */
- immediate_size_expand = 0;
+ /* Indicate no valid break/continue context by setting these variables
+ to some non-null, non-label value. We'll notice and emit the proper
+ error message in c_finish_bc_stmt. */
+ c_break_label = c_cont_label = size_zero_node;
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
if (decl1 == 0)
- {
- immediate_size_expand = old_immediate_size_expand;
- return 0;
- }
+ return 0;
decl_attributes (&decl1, attributes, 0);
push_scope ();
declare_parm_level ();
- make_decl_rtl (current_function_decl, NULL);
-
restype = TREE_TYPE (TREE_TYPE (current_function_decl));
/* Promote the value to int before returning it. */
if (c_promoting_integer_type_p (restype))
{
/* It retains unsignedness if not really getting wider. */
- if (TREE_UNSIGNED (restype)
+ if (TYPE_UNSIGNED (restype)
&& (TYPE_PRECISION (restype)
== TYPE_PRECISION (integer_type_node)))
restype = unsigned_type_node;
DECL_RESULT (current_function_decl)
= build_decl (RESULT_DECL, NULL_TREE, restype);
- /* If this fcn was already referenced via a block-scope `extern' decl
- (or an implicit decl), propagate certain information about the usage. */
- if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl)))
- TREE_ADDRESSABLE (current_function_decl) = 1;
-
- immediate_size_expand = old_immediate_size_expand;
-
start_fname_decls ();
return 1;
warning if we got here because ARG_INFO_TYPES was error_mark_node
(this happens when a function definition has just an ellipsis in
its parameter list). */
- else if (warn_traditional && !in_system_header
- && DECL_CONTEXT (fndecl) == current_file_decl
+ else if (warn_traditional && !in_system_header && !current_function_scope
&& ARG_INFO_TYPES (arg_info) != error_mark_node)
warning ("%Jtraditional C rejects ISO C style function definitions",
fndecl);
declared for the arg. ISO C says we take the unqualified
type for parameters declared with qualified type. */
if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
- TYPE_MAIN_VARIANT (TREE_VALUE (type)),
- COMPARE_STRICT))
+ TYPE_MAIN_VARIANT (TREE_VALUE (type))))
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
== TYPE_MAIN_VARIANT (TREE_VALUE (type)))
}
}
+/* A subroutine of store_parm_decls called via walk_tree. Mark all
+ decls non-local. */
+
+static tree
+set_decl_nonlocal (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
+{
+ tree t = *tp;
+
+ if (DECL_P (t))
+ {
+ DECL_NONLOCAL (t) = 1;
+ *walk_subtrees = 0;
+ }
+ else if (TYPE_P (t))
+ *walk_subtrees = 0;
+
+ return NULL;
+}
+
/* Store the parameter declarations into the current function declaration.
This is called after parsing the parameter declarations, before
digesting the body of the function.
allocate_struct_function (fndecl);
/* Begin the statement tree for this function. */
- begin_stmt_tree (&DECL_SAVED_TREE (fndecl));
+ DECL_SAVED_TREE (fndecl) = push_stmt_list ();
/* If this is a nested function, save away the sizes of any
variable-size types so that we can expand them when generating
for (t = DECL_LANG_SPECIFIC (fndecl)->pending_sizes;
t;
t = TREE_CHAIN (t))
- SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = context;
- }
+ {
+ /* We will have a nonlocal use of whatever variables are
+ buried inside here. */
+ walk_tree (&TREE_OPERAND (TREE_VALUE (t), 0),
+ set_decl_nonlocal, NULL, NULL);
- /* This function is being processed in whole-function mode. */
- cfun->x_whole_function_mode_p = 1;
+ SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = context;
+ }
+ }
/* 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
+/* Give FNDECL and all its nested functions to cgraph for compilation. */
+
+static void
+c_finalize (tree fndecl)
+{
+ struct cgraph_node *cgn;
+
+ /* Handle attribute((warn_unused_result)). Relies on gimple input. */
+ c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
+
+ /* ??? Objc emits functions after finalizing the compilation unit.
+ This should be cleaned up later and this conditional removed. */
+ if (cgraph_global_info_ready)
+ {
+ c_expand_body (fndecl);
+ return;
+ }
+
+ /* Finalize all nested functions now. */
+ cgn = cgraph_node (fndecl);
+ for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
+ c_finalize (cgn->decl);
+
+ cgraph_finalize_function (fndecl, false);
+}
+
/* Finish up a function declaration and compile that function
all the way to assembler language output. The free the storage
for the function definition.
{
tree fndecl = current_function_decl;
- /* When a function declaration is totally empty, e.g.
- void foo(void) { }
- (the argument list is irrelevant) the compstmt rule will not
- bother calling push_scope/pop_scope, which means we get here with
- the scope stack out of sync. Detect this situation by noticing
- that current_scope is still as store_parm_decls left it, and do
- a dummy push/pop to get back to consistency.
- Note that the call to push_scope does not actually push another
- scope - see there for details. */
-
- if (current_scope->parm_flag && next_is_function_body)
- {
- push_scope ();
- pop_scope ();
- }
-
if (TREE_CODE (fndecl) == FUNCTION_DECL
&& targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
{
}
else
{
-#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
+ c_finish_return (integer_zero_node);
}
}
- finish_fname_decls ();
-
/* Tie off the statement tree for this function. */
- finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+ DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
+
+ finish_fname_decls ();
/* Complain if there's just no return statement. */
if (warn_return_type
&& current_function_returns_null)
warning ("this function may return with or without a value");
- /* We're leaving the context of this function, so zap cfun.
- It's still in DECL_STRUCT_FUNCTION , and we'll restore it in
- tree_rest_of_compilation. */
- cfun = NULL;
+ /* Store the end of the function, so that we get good line number
+ info for the epilogue. */
+ cfun->function_end_locus = input_location;
- /* ??? Objc emits functions after finalizing the compilation unit.
- This should be cleaned up later and this conditional removed. */
- if (!cgraph_global_info_ready)
- cgraph_finalize_function (fndecl, false);
- else
- c_expand_body (fndecl);
- current_function_decl = NULL;
-}
+ /* If we don't have ctors/dtors sections, and this is a static
+ constructor or destructor, it must be recorded now. */
+ if (DECL_STATIC_CONSTRUCTOR (fndecl)
+ && !targetm.have_ctors_dtors)
+ static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
+ if (DECL_STATIC_DESTRUCTOR (fndecl)
+ && !targetm.have_ctors_dtors)
+ static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
-/* Generate the RTL for the body of FNDECL. If NESTED_P is nonzero,
- then we are already in the process of generating RTL for another
- function. */
+ /* Genericize before inlining. Delay genericizing nested functions
+ until their parent function is genericized. Since finalizing
+ requires GENERIC, delay that as well. */
-static void
-c_expand_body_1 (tree fndecl, int nested_p)
-{
- if (nested_p)
- {
- /* Make sure that we will evaluate variable-sized types involved
- in our function's type. */
- expand_pending_sizes (DECL_LANG_SPECIFIC (fndecl)->pending_sizes);
-
- /* Squirrel away our current state. */
- push_function_context ();
- }
-
- tree_rest_of_compilation (fndecl, nested_p);
-
- if (nested_p)
- /* Return to the enclosing function. */
- pop_function_context ();
-
- if (DECL_STATIC_CONSTRUCTOR (fndecl))
+ if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node)
{
- if (targetm.have_ctors_dtors)
- targetm.asm_out.constructor (XEXP (DECL_RTL (fndecl), 0),
- DEFAULT_INIT_PRIORITY);
+ if (!decl_function_context (fndecl))
+ {
+ c_genericize (fndecl);
+ lower_nested_functions (fndecl);
+ c_finalize (fndecl);
+ }
else
- static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
+ {
+ /* Register this function with cgraph just far enough to get it
+ added to our parent's nested function list. Handy, since the
+ C front end doesn't have such a list. */
+ (void) cgraph_node (fndecl);
+ }
}
- if (DECL_STATIC_DESTRUCTOR (fndecl))
- {
- if (targetm.have_ctors_dtors)
- targetm.asm_out.destructor (XEXP (DECL_RTL (fndecl), 0),
- DEFAULT_INIT_PRIORITY);
- else
- static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
- }
+ /* We're leaving the context of this function, so zap cfun.
+ It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
+ tree_rest_of_compilation. */
+ cfun = NULL;
+ current_function_decl = NULL;
}
-/* Like c_expand_body_1 but only for unnested functions. */
+/* Generate the RTL for the body of FNDECL. */
void
c_expand_body (tree fndecl)
{
- if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node)
- c_expand_body_1 (fndecl, 0);
+ if (!DECL_INITIAL (fndecl)
+ || DECL_INITIAL (fndecl) == error_mark_node)
+ return;
+
+ tree_rest_of_compilation (fndecl, false);
+
+ if (DECL_STATIC_CONSTRUCTOR (fndecl)
+ && targetm.have_ctors_dtors)
+ targetm.asm_out.constructor (XEXP (DECL_RTL (fndecl), 0),
+ DEFAULT_INIT_PRIORITY);
+ if (DECL_STATIC_DESTRUCTOR (fndecl)
+ && targetm.have_ctors_dtors)
+ targetm.asm_out.destructor (XEXP (DECL_RTL (fndecl), 0),
+ DEFAULT_INIT_PRIORITY);
}
\f
/* Check the declarations given in a for-loop for satisfying the C99
f->language = p;
p->base.x_stmt_tree = c_stmt_tree;
- p->base.x_scope_stmt_stack = c_scope_stmt_stack;
- p->x_in_iteration_stmt = c_in_iteration_stmt;
- p->x_in_case_stmt = c_in_case_stmt;
+ p->x_break_label = c_break_label;
+ p->x_cont_label = c_cont_label;
+ p->x_switch_stack = c_switch_stack;
p->returns_value = current_function_returns_value;
p->returns_null = current_function_returns_null;
p->returns_abnormally = current_function_returns_abnormally;
}
c_stmt_tree = p->base.x_stmt_tree;
- c_scope_stmt_stack = p->base.x_scope_stmt_stack;
- c_in_iteration_stmt = p->x_in_iteration_stmt;
- c_in_case_stmt = p->x_in_case_stmt;
+ c_break_label = p->x_break_label;
+ c_cont_label = p->x_cont_label;
+ c_switch_stack = p->x_switch_stack;
current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null;
current_function_returns_abnormally = p->returns_abnormally;
return &c_stmt_tree;
}
-/* Returns the stack of SCOPE_STMTs for the current function. */
-
-tree *
-current_scope_stmt_stack (void)
-{
- return &c_scope_stmt_stack;
-}
-
/* Nonzero if TYPE is an anonymous union or struct type. Always 0 in
C. */
{
}
-/* Return a new COMPOUND_STMT, after adding it to the current
- statement tree. */
-
-tree
-c_begin_compound_stmt (void)
-{
- tree stmt;
-
- /* Create the COMPOUND_STMT. */
- stmt = add_stmt (build_stmt (COMPOUND_STMT, NULL_TREE));
-
- return stmt;
-}
-
-/* Expand T (a DECL_STMT) if it declares an entity not handled by the
- common code. */
-
-void
-c_expand_decl_stmt (tree t)
-{
- tree decl = DECL_STMT_DECL (t);
-
- /* Expand nested functions. */
- if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_CONTEXT (decl) == current_function_decl
- && DECL_SAVED_TREE (decl))
- c_expand_body_1 (decl, 1);
-}
-
/* Return the global value of T as a symbol. */
tree
tree *vec = xmalloc (sizeof (tree) * len);
size_t i;
tree decl;
-
+
/* Process the decls in the order they were written. */
for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
vec[i] = decl;
wrapup_global_declarations (vec, len);
check_global_declarations (vec, len);
-
+
free (vec);
}
return;
/* Process all file scopes in this compilation. */
- for (t = current_file_decl; t; t = TREE_CHAIN (t))
+ for (t = all_translation_units; t; t = TREE_CHAIN (t))
c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
/* Now do the same for the externals scope. */