diff options
Diffstat (limited to 'gcc-4.9/gcc/c/c-decl.c')
-rw-r--r-- | gcc-4.9/gcc/c/c-decl.c | 374 |
1 files changed, 349 insertions, 25 deletions
diff --git a/gcc-4.9/gcc/c/c-decl.c b/gcc-4.9/gcc/c/c-decl.c index df84980e3..ac3819823 100644 --- a/gcc-4.9/gcc/c/c-decl.c +++ b/gcc-4.9/gcc/c/c-decl.c @@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see #include "hash-table.h" #include "langhooks-def.h" #include "pointer-set.h" +#include "l-ipo.h" #include "plugin.h" #include "c-family/c-ada-spec.h" #include "cilk.h" @@ -537,6 +538,27 @@ static tree grokdeclarator (const struct c_declarator *, bool *, enum deprecated_states); static tree grokparms (struct c_arg_info *, bool); static void layout_array_type (tree); +static void pop_ext_scope (void); + +/* LIPO support */ +/* The list of block nodes. A member node is created + when an external scope is popped. */ +static GTY (()) vec<tree, va_gc> *ext_blocks = NULL; +static inline void +apply_for_each_ext_block (void (*func) (tree)) +{ + if (L_IPO_COMP_MODE) + { + size_t i; + tree eb; + + for (i = 0; + ext_blocks->iterate (i, &eb); + ++i) + func (BLOCK_VARS (eb)); + } +} + /* T is a statement. Add it to the statement-tree. This is the C/ObjC version--C++ has a slightly different version of this @@ -686,6 +708,8 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible, b->shadowed = *here; *here = b; + + add_decl_to_current_module_scope (decl, scope); } /* Clear the binding structure B, stick it on the binding_freelist, @@ -1214,8 +1238,18 @@ pop_scope (void) binding in the home scope. */ if (!b->nested) { - DECL_CHAIN (p) = BLOCK_VARS (block); - BLOCK_VARS (block) = p; + /* In LIPO mode compilation, ext_scope is popped out + at end of each module to block name lookup across + modules. The ext_scope is used to keep the list of + global variables in that module scope. Other decls + are filtered out. */ + if (!L_IPO_COMP_MODE + || scope != external_scope + || TREE_CODE (p) == VAR_DECL) + { + DECL_CHAIN (p) = BLOCK_VARS (block); + BLOCK_VARS (block) = p; + } } else if (VAR_OR_FUNCTION_DECL_P (p) && scope != file_scope) { @@ -1316,6 +1350,11 @@ push_file_scope (void) push_scope (); file_scope = current_scope; + /* LIPO support -- do this before file scope bindings + are created for visible_builtins -- only need to remember + external scope bindings. */ + push_module_scope (); + start_fname_decls (); for (decl = visible_builtins; decl; decl = DECL_CHAIN (decl)) @@ -1350,7 +1389,18 @@ pop_file_scope (void) pop_scope (); file_scope = 0; - maybe_apply_pending_pragma_weaks (); + if (!L_IPO_COMP_MODE) + maybe_apply_pending_pragma_weaks (); + else + { + pop_ext_scope (); + gcc_assert (current_scope == 0 && external_scope == 0); + push_scope (); + external_scope = current_scope; + /* Prepare for parsing for the next module -- including + builtin re-binding. */ + pop_module_scope (); + } } /* Adjust the bindings for the start of a statement expression. */ @@ -2552,7 +2602,9 @@ warn_if_shadowing (tree new_decl) struct c_binding *b; /* Shadow warnings wanted? */ - if (!warn_shadow + if (!(warn_shadow + || warn_shadow_local + || warn_shadow_compatible_local) /* No shadow warnings for internally generated vars. */ || DECL_IS_BUILTIN (new_decl) /* No shadow warnings for vars made for inlining. */ @@ -2569,14 +2621,25 @@ warn_if_shadowing (tree new_decl) tree old_decl = b->decl; if (old_decl == error_mark_node) - { - warning (OPT_Wshadow, "declaration of %q+D shadows previous " - "non-variable", new_decl); - break; - } + warning (OPT_Wshadow, "declaration of %q+D shadows previous " + "non-variable", new_decl); else if (TREE_CODE (old_decl) == PARM_DECL) - warning (OPT_Wshadow, "declaration of %q+D shadows a parameter", - new_decl); + { + enum opt_code warning_code; + + /* If '-Wshadow-compatible-local' is specified without other + -Wshadow flags, we will warn only when the types of the + shadowing variable (i.e. new_decl) and the shadowed variable + (old_decl) are compatible. */ + if (comptypes (TREE_TYPE (old_decl), TREE_TYPE (new_decl))) + warning_code = OPT_Wshadow_compatible_local; + else + warning_code = OPT_Wshadow_local; + warning (warning_code, + "declaration of %q+D shadows a parameter", new_decl); + warning_at (DECL_SOURCE_LOCATION (old_decl), warning_code, + "shadowed declaration is here"); + } else if (DECL_FILE_SCOPE_P (old_decl)) { /* Do not warn if a variable shadows a function, unless @@ -2586,23 +2649,34 @@ warn_if_shadowing (tree new_decl) && !FUNCTION_POINTER_TYPE_P (TREE_TYPE (new_decl))) continue; - warning_at (DECL_SOURCE_LOCATION (new_decl), OPT_Wshadow, - "declaration of %qD shadows a global declaration", - new_decl); + warning (OPT_Wshadow, "declaration of %q+D shadows a global " + "declaration", new_decl); + warning_at (DECL_SOURCE_LOCATION (old_decl), OPT_Wshadow, + "shadowed declaration is here"); } else if (TREE_CODE (old_decl) == FUNCTION_DECL && DECL_BUILT_IN (old_decl)) - { warning (OPT_Wshadow, "declaration of %q+D shadows " "a built-in function", new_decl); - break; - } else - warning (OPT_Wshadow, "declaration of %q+D shadows a previous local", - new_decl); - - warning_at (DECL_SOURCE_LOCATION (old_decl), OPT_Wshadow, - "shadowed declaration is here"); + { + enum opt_code warning_code; + + /* If '-Wshadow-compatible-local' is specified without other + -Wshadow flags, we will warn only when the types of the + shadowing variable (i.e. new_decl) and the shadowed variable + (old_decl) are compatible. */ + if (comptypes (TREE_TYPE (old_decl), TREE_TYPE (new_decl))) + warning_code = OPT_Wshadow_compatible_local; + else + warning_code = OPT_Wshadow_local; + warning (warning_code, + "declaration of %q+D shadows a previous local", + new_decl); + + warning_at (DECL_SOURCE_LOCATION (old_decl), warning_code, + "shadowed declaration is here"); + } break; } @@ -4486,12 +4560,25 @@ finish_decl (tree decl, location_t init_loc, tree init, when a tentative file-scope definition is seen. But at end of compilation, do output code for them. */ DECL_DEFER_OUTPUT (decl) = 1; + + /* In LIPO mode, create varpool_node early + enough so that module id of the current source file being + parsed is captured. */ + if (flag_dyn_ipa && TREE_CODE (decl) == VAR_DECL) + varpool_node_for_decl (decl); + if (asmspec && C_DECL_REGISTER (decl)) DECL_HARD_REGISTER (decl) = 1; rest_of_decl_compilation (decl, true, 0); } else { + /* LIPO: capture module id. */ + if (flag_dyn_ipa + && TREE_CODE (decl) == VAR_DECL + && TREE_STATIC (decl)) + varpool_node_for_decl (decl); + /* In conjunction with an ASMSPEC, the `register' keyword indicates that we should place the variable in a particular register. */ @@ -5911,7 +5998,7 @@ grokdeclarator (const struct c_declarator *declarator, else if (declspecs->align_log != -1) { alignas_align = 1U << declspecs->align_log; - if (alignas_align < TYPE_ALIGN_UNIT (type)) + if (alignas_align < min_align_of_type (type)) { if (name) error_at (loc, "%<_Alignas%> specifiers cannot reduce " @@ -10391,7 +10478,12 @@ c_write_global_declarations (void) through wrapup_global_declarations and check_global_declarations. */ FOR_EACH_VEC_ELT (*all_translation_units, i, t) c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t))); - c_write_global_declarations_1 (BLOCK_VARS (ext_block)); + if (ext_block) + c_write_global_declarations_1 (BLOCK_VARS (ext_block)); + apply_for_each_ext_block (c_write_global_declarations_1); + + if (L_IPO_COMP_MODE) + maybe_apply_pending_pragma_weaks (); timevar_stop (TV_PHASE_DEFERRED); timevar_start (TV_PHASE_OPT_GEN); @@ -10410,7 +10502,9 @@ c_write_global_declarations (void) timevar_push (TV_SYMOUT); FOR_EACH_VEC_ELT (*all_translation_units, i, t) c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t))); - c_write_global_declarations_2 (BLOCK_VARS (ext_block)); + if (ext_block) + c_write_global_declarations_2 (BLOCK_VARS (ext_block)); + apply_for_each_ext_block (c_write_global_declarations_2); timevar_pop (TV_SYMOUT); } @@ -10418,6 +10512,236 @@ c_write_global_declarations (void) timevar_stop (TV_PHASE_DBGINFO); } + +/* LIPO support */ + +typedef struct GTY (()) c_sb +{ + tree decl; + tree id; + tree decl_copy_pre; /* copy at the start of file parsing. */ + tree decl_copy_post; /* copy at the end of module_scope. */ + int invisible; +} c_saved_builtin; + +static GTY (()) vec<c_saved_builtin, va_gc> *saved_builtins = NULL; + +/* Return the needed size of lang_decl structure for tree T. */ + +int +c_get_lang_decl_size (tree t) +{ + if (!DECL_LANG_SPECIFIC (t)) + return 0; + return sizeof (struct lang_decl); +} + +/* Return true if S is external or file scope. */ + +bool +c_is_global_scope (tree decl ATTRIBUTE_UNUSED, void *s) +{ + struct c_scope *scope = (struct c_scope *)s; + + if (scope == external_scope || scope == file_scope) + return true; + + return false; +} + +/* Add DECL to the list of builtins. */ + +void +c_add_built_in_decl (tree decl) +{ + c_saved_builtin *sb; + struct c_binding *b = NULL; + + if (!flag_dyn_ipa) + return; + + if (at_eof) + return; + + if (parser_parsing_start) + return; + + sb = vec_safe_push (saved_builtins, c_saved_builtin ()); + sb->decl = decl; + sb->decl_copy_pre = NULL; + sb->decl_copy_post = NULL; + sb->id = get_type_or_decl_name (decl); + + switch (TREE_CODE (decl)) + { + case TYPE_DECL: + case FUNCTION_DECL: + case CONST_DECL: + b = I_SYMBOL_BINDING (sb->id); + break; + case ENUMERAL_TYPE: + case UNION_TYPE: + case RECORD_TYPE: + b = I_TAG_BINDING (sb->id); + break; + default: + gcc_unreachable (); + } + + gcc_assert (b && b->decl == decl + && b->id == sb->id && b->depth == 0); + sb->invisible = b->invisible; +} + +/* Pop the external scope at the end of parsing of a file. */ + +static void +pop_ext_scope (void) +{ + tree ext_b; + if (!L_IPO_COMP_MODE) + return; + ext_b = pop_scope (); + vec_safe_push (ext_blocks, ext_b); + gcc_assert (!current_scope); + external_scope = 0; + + /* Now remove non var_decls from BLOCK_VARS -- + this is needed to avoid tree-chain contamination + from other modules due to builtin (shared) decls. */ + { + tree *p = &BLOCK_VARS (ext_b); + tree decl = BLOCK_VARS (ext_b); + for (; decl; decl = TREE_CHAIN (decl)) + { + if (TREE_CODE (decl) != VAR_DECL) + { + gcc_assert (0); + *p = TREE_CHAIN (decl); + } + else + p = &TREE_CHAIN (decl); + } + } +} + +/* Save a copy of SB->decl before file parsing start. */ + +static void +c_save_built_in_decl_pre_parsing_1 (c_saved_builtin *sb) +{ + tree decl = sb->decl; + + sb->decl_copy_pre = lipo_save_decl (decl); + sb->decl_copy_post = NULL; + return; +} + +/* Make copies of builtin decls before file parsing. */ + +void +c_save_built_in_decl_pre_parsing (void) +{ + size_t i; + c_saved_builtin *bi; + + for (i = 0; + saved_builtins->iterate (i, &bi); + ++i) + c_save_built_in_decl_pre_parsing_1 (bi); +} + +/* Restore builtins to their values before file parsing ( + the initial default value). */ + +void +c_restore_built_in_decl_pre_parsing (void) +{ + size_t i; + c_saved_builtin *bi; + + /* Now re-bind the builtins in the external scope. */ + gcc_assert (current_scope && current_scope == external_scope); + for (i = 0; + saved_builtins->iterate (i, &bi); + ++i) + { + tree id; + tree decl = bi->decl; + id = bi->id; + + lipo_restore_decl (decl, bi->decl_copy_pre); + if (id) + bind (id, decl, external_scope, + bi->invisible, false /*nested*/, + DECL_SOURCE_LOCATION (decl)); + } +} + +/* Save values of builtins after parsing of a file. */ + +void +c_save_built_in_decl_post_parsing (void) +{ + size_t i; + c_saved_builtin *bi; + + for (i = 0; + saved_builtins->iterate (i, &bi); + ++i) + { + /* Skip builtin decls in the predefined state. + The static flag for defined builtins are not set, so + do not check it. */ + if (DECL_ARTIFICIAL (bi->decl) + || TREE_CODE (bi->decl) != FUNCTION_DECL + || !DECL_STRUCT_FUNCTION (bi->decl)) + continue; + /* Remember the defining module. */ + cgraph_link_node (cgraph_get_create_node (bi->decl)); + if (!bi->decl_copy_post) + bi->decl_copy_post = lipo_save_decl (bi->decl); + } +} + +/* Restore builtins to their values (non-default) + after parsing finishes. */ + +void +c_restore_built_in_decl_post_parsing (void) +{ + c_saved_builtin *bi; + unsigned i; + for (i = 0; + saved_builtins->iterate (i, &bi); + ++i) + { + tree decl = bi->decl; + /* Now restore the decl's state */ + if (bi->decl_copy_post) + lipo_restore_decl (decl, bi->decl_copy_post); + } +} + +/* Return true if type T is compiler generated. */ + +bool +c_is_compiler_generated_type (tree t ATTRIBUTE_UNUSED) +{ + return false; +} + +/* Return 1 if lang specific attribute of T1 and T2 are + equivalent. */ + +int +c_cmp_lang_type (tree t1 ATTRIBUTE_UNUSED, + tree t2 ATTRIBUTE_UNUSED) +{ + return 1; +} + + /* Register reserved keyword WORD as qualifier for address space AS. */ void |