diff options
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r-- | gcc/c-decl.c | 229 |
1 files changed, 163 insertions, 66 deletions
diff --git a/gcc/c-decl.c b/gcc/c-decl.c index b03ba80..d0fc708 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -49,6 +49,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "timevar.h" #include "c-common.h" #include "c-pragma.h" +#include "langhooks.h" +#include "tree-mudflap.h" +#include "tree-simple.h" +#include "diagnostic.h" +#include "tree-dump.h" #include "cgraph.h" #include "hashtab.h" #include "libfuncs.h" @@ -1664,7 +1669,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) 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; @@ -2113,10 +2118,6 @@ lookup_label (tree name) 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) { @@ -2936,7 +2937,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree) in a particular register. */ if (C_DECL_REGISTER (decl)) { - DECL_C_HARD_REGISTER (decl) = 1; + DECL_HARD_REGISTER (decl) = 1; /* This cannot be done for a structure with volatile fields, on which DECL_REGISTER will have been reset. */ @@ -3304,11 +3305,14 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name) else w = tree_low_cst (*width, 1); - if (TREE_CODE (*type) == ENUMERAL_TYPE - && (w < min_precision (TYPE_MIN_VALUE (*type), TYPE_UNSIGNED (*type)) - || w < min_precision (TYPE_MAX_VALUE (*type), - TYPE_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); + } } /* Given declspecs and a declarator, @@ -4059,6 +4063,11 @@ grokdeclarator (tree declarator, tree declspecs, 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)) { @@ -5251,7 +5260,7 @@ finish_struct (tree t, tree fieldlist, tree attributes) 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; @@ -5386,9 +5395,10 @@ tree 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); @@ -5418,27 +5428,20 @@ finish_enum (tree enumtype, tree values, tree attributes) 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; - TYPE_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); @@ -5454,6 +5457,7 @@ finish_enum (tree enumtype, tree values, tree attributes) for (pair = values; pair; pair = TREE_CHAIN (pair)) { tree enu = TREE_PURPOSE (pair); + tree ini = DECL_INITIAL (enu); TREE_TYPE (enu) = enumtype; @@ -5464,18 +5468,27 @@ finish_enum (tree enumtype, tree values, tree attributes) 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)) { @@ -5491,6 +5504,7 @@ finish_enum (tree enumtype, tree values, tree attributes) TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype); TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype); TYPE_UNSIGNED (tem) = TYPE_UNSIGNED (enumtype); + TYPE_LANG_SPECIFIC (tem) = TYPE_LANG_SPECIFIC (enumtype); } /* Finish debugging output for this type. */ @@ -6085,6 +6099,25 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info) } } +/* 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. @@ -6142,7 +6175,14 @@ store_parm_decls (void) 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); + + SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = context; + } } /* This function is being processed in whole-function mode. */ @@ -6156,6 +6196,32 @@ store_parm_decls (void) cfun->x_dont_save_pending_sizes_p = 1; } +/* 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. @@ -6253,17 +6319,44 @@ finish_function (void) && current_function_returns_null) warning ("this function may return with or without a value"); + /* Store the end of the function, so that we get good line number + info for the epilogue. */ + cfun->function_end_locus = input_location; + + /* 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); + + /* Genericize before inlining. Delay genericizing nested functions + until their parent function is genericized. Since finalizing + requires GENERIC, delay that as well. */ + + if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node) + { + if (!decl_function_context (fndecl)) + { + c_genericize (fndecl); + lower_nested_functions (fndecl); + c_finalize (fndecl); + } + else + { + /* 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); + } + } + /* We're leaving the context of this function, so zap cfun. - It's still in DECL_STRUCT_FUNCTION , and we'll restore it in + It's still in DECL_STRUCT_FUNCTION, and we'll restore it in tree_rest_of_compilation. */ cfun = NULL; - - /* ??? 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; } @@ -6290,23 +6383,14 @@ c_expand_body_1 (tree fndecl, int nested_p) /* Return to the enclosing function. */ pop_function_context (); - if (DECL_STATIC_CONSTRUCTOR (fndecl)) - { - if (targetm.have_ctors_dtors) - targetm.asm_out.constructor (XEXP (DECL_RTL (fndecl), 0), - DEFAULT_INIT_PRIORITY); - else - static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors); - } - - 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); - } + 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); } /* Like c_expand_body_1 but only for unnested functions. */ @@ -6512,19 +6596,32 @@ c_begin_compound_stmt (void) return stmt; } -/* Expand T (a DECL_STMT) if it declares an entity not handled by the +/* Expand DECL if it declares an entity not handled by the common code. */ -void -c_expand_decl_stmt (tree t) +int +c_expand_decl (tree decl) { - tree decl = DECL_STMT_DECL (t); - + if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl)) + { + /* Let the back-end know about this variable. */ + if (!anon_aggr_type_p (TREE_TYPE (decl))) + emit_local_var (decl); + else + expand_anon_union_decl (decl, NULL_TREE, + DECL_ANON_UNION_ELEMS (decl)); + } + else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)) + make_rtl_for_local_static (decl); /* Expand nested functions. */ - if (TREE_CODE (decl) == FUNCTION_DECL - && DECL_CONTEXT (decl) == current_function_decl - && DECL_SAVED_TREE (decl)) + else if (TREE_CODE (decl) == FUNCTION_DECL + && DECL_CONTEXT (decl) == current_function_decl + && DECL_SAVED_TREE (decl)) c_expand_body_1 (decl, 1); + else + return 0; + + return 1; } /* Return the global value of T as a symbol. */ |