diff options
Diffstat (limited to 'gcc-4.9/gcc/cp/decl2.c')
-rw-r--r-- | gcc-4.9/gcc/cp/decl2.c | 142 |
1 files changed, 107 insertions, 35 deletions
diff --git a/gcc-4.9/gcc/cp/decl2.c b/gcc-4.9/gcc/cp/decl2.c index 4fc03e9..074108e 100644 --- a/gcc-4.9/gcc/cp/decl2.c +++ b/gcc-4.9/gcc/cp/decl2.c @@ -99,6 +99,10 @@ static GTY(()) vec<tree, va_gc> *pending_statics; may need to emit outline anyway. */ static GTY(()) vec<tree, va_gc> *deferred_fns; +/* A list of functions which we might want to set DECL_COMDAT on at EOF. */ + +static GTY(()) vec<tree, va_gc> *maybe_comdat_fns; + /* A list of decls that use types with no linkage, which we need to make sure are defined. */ static GTY(()) vec<tree, va_gc> *no_linkage_decls; @@ -608,7 +612,7 @@ check_classfn (tree ctype, tree function, tree template_parms) int ix; bool is_template; tree pushed_scope; - + if (DECL_USE_TEMPLATE (function) && !(TREE_CODE (function) == TEMPLATE_DECL && DECL_TEMPLATE_SPECIALIZATION (function)) @@ -717,7 +721,7 @@ check_classfn (tree ctype, tree function, tree template_parms) pop_scope (pushed_scope); return OVL_CURRENT (fndecls); } - + error_at (DECL_SOURCE_LOCATION (function), "prototype for %q#D does not match any in class %qT", function, ctype); @@ -1582,7 +1586,7 @@ coerce_new_type (tree type) if (TREE_PURPOSE (args)) { /* [basic.stc.dynamic.allocation] - + The first parameter shall not have an associated default argument. */ error ("the first parameter of %<operator new%> cannot " @@ -1893,6 +1897,12 @@ mark_needed (tree decl) definition. */ struct cgraph_node *node = cgraph_get_create_node (decl); node->forced_by_abi = true; + + /* #pragma interface and -frepo code can call mark_needed for + maybe-in-charge 'tors; mark the clones as well. */ + tree clone; + FOR_EACH_CLONE (clone, decl) + mark_needed (clone); } else if (TREE_CODE (decl) == VAR_DECL) { @@ -1931,11 +1941,6 @@ decl_needed_p (tree decl) if (flag_keep_inline_dllexport && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) return true; - /* Virtual functions might be needed for devirtualization. */ - if (flag_devirtualize - && TREE_CODE (decl) == FUNCTION_DECL - && DECL_VIRTUAL_P (decl)) - return true; /* Otherwise, DECL does not need to be emitted -- yet. A subsequent reference to DECL might cause it to be emitted later. */ return false; @@ -2206,7 +2211,7 @@ determine_visibility (tree decl) if (DECL_VISIBILITY_SPECIFIED (fn)) { DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn); - DECL_VISIBILITY_SPECIFIED (decl) = + DECL_VISIBILITY_SPECIFIED (decl) = DECL_VISIBILITY_SPECIFIED (fn); } else @@ -2287,7 +2292,7 @@ determine_visibility (tree decl) tree attribs = (TREE_CODE (decl) == TYPE_DECL ? TYPE_ATTRIBUTES (TREE_TYPE (decl)) : DECL_ATTRIBUTES (decl)); - + if (args != error_mark_node) { tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo)); @@ -2680,17 +2685,7 @@ import_export_decl (tree decl) { /* The repository indicates that this entity should be defined here. Make sure the back end honors that request. */ - if (VAR_P (decl)) - mark_needed (decl); - else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl) - || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)) - { - tree clone; - FOR_EACH_CLONE (clone, decl) - mark_needed (clone); - } - else - mark_needed (decl); + mark_needed (decl); /* Output the definition as an ordinary strong definition. */ DECL_EXTERNAL (decl) = 0; DECL_INTERFACE_KNOWN (decl) = 1; @@ -2921,6 +2916,27 @@ get_guard (tree decl) return guard; } +/* Return an atomic load of src with the appropriate memory model. */ + +static tree +build_atomic_load_byte (tree src, HOST_WIDE_INT model) +{ + tree ptr_type = build_pointer_type (char_type_node); + tree mem_model = build_int_cst (integer_type_node, model); + tree t, addr, val; + unsigned int size; + int fncode; + + size = tree_to_uhwi (TYPE_SIZE_UNIT (char_type_node)); + + fncode = BUILT_IN_ATOMIC_LOAD_N + exact_log2 (size) + 1; + t = builtin_decl_implicit ((enum built_in_function) fncode); + + addr = build1 (ADDR_EXPR, ptr_type, src); + val = build_call_expr (t, 2, addr, mem_model); + return val; +} + /* Return those bits of the GUARD variable that should be set when the guarded entity is actually initialized. */ @@ -2947,12 +2963,14 @@ get_guard_bits (tree guard) variable has already been initialized. */ tree -get_guard_cond (tree guard) +get_guard_cond (tree guard, bool thread_safe) { tree guard_value; - /* Check to see if the GUARD is zero. */ - guard = get_guard_bits (guard); + if (!thread_safe) + guard = get_guard_bits (guard); + else + guard = build_atomic_load_byte (guard, MEMMODEL_ACQUIRE); /* Mask off all but the low bit. */ if (targetm.cxx.guard_mask_bit ()) @@ -2986,7 +3004,7 @@ set_guard (tree guard) guard_init = integer_one_node; if (!same_type_p (TREE_TYPE (guard_init), TREE_TYPE (guard))) guard_init = convert (TREE_TYPE (guard), guard_init); - return cp_build_modify_expr (guard, NOP_EXPR, guard_init, + return cp_build_modify_expr (guard, NOP_EXPR, guard_init, tf_warning_or_error); } @@ -3038,9 +3056,15 @@ get_local_tls_init_fn (void) void_list_node)); SET_DECL_LANGUAGE (fn, lang_c); TREE_PUBLIC (fn) = false; + TREE_STATIC (fn) = true; DECL_ARTIFICIAL (fn) = true; mark_used (fn); SET_IDENTIFIER_GLOBAL_VALUE (sname, fn); + /* In LIPO mode make sure we record the new global value so that it + is cleared before parsing the next aux module. */ + if (L_IPO_COMP_MODE && !is_parsing_done_p ()) + add_decl_to_current_module_scope (fn, + NAMESPACE_LEVEL (global_namespace)); } return fn; } @@ -3105,6 +3129,11 @@ get_tls_init_fn (tree var) DECL_BEFRIENDING_CLASSES (fn) = var; SET_IDENTIFIER_GLOBAL_VALUE (sname, fn); + /* In LIPO mode make sure we record the new global value so that it + is cleared before parsing the next aux module. */ + if (L_IPO_COMP_MODE && !is_parsing_done_p ()) + add_decl_to_current_module_scope (fn, + NAMESPACE_LEVEL (global_namespace)); } return fn; } @@ -3162,6 +3191,11 @@ get_tls_wrapper_fn (tree var) DECL_BEFRIENDING_CLASSES (fn) = var; SET_IDENTIFIER_GLOBAL_VALUE (sname, fn); + /* In LIPO mode make sure we record the new global value so that it + is cleared before parsing the next aux module. */ + if (L_IPO_COMP_MODE && !is_parsing_done_p ()) + add_decl_to_current_module_scope (fn, + NAMESPACE_LEVEL (global_namespace)); } return fn; } @@ -3473,7 +3507,7 @@ get_priority_info (int priority) some optimizers (enabled by -O2 -fprofile-arcs) might crash when trying to refer to a temporary variable that does not have it's DECL_CONTECT() properly set. */ -static tree +static tree fix_temporary_vars_context_r (tree *node, int * /*unused*/, void * /*unused1*/) @@ -3520,7 +3554,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp) /* Make sure temporary variables in the initialiser all have their DECL_CONTEXT() set to a value different from NULL_TREE. This can happen when global variables initialisers are built. - In that case, the DECL_CONTEXT() of the global variables _AND_ of all + In that case, the DECL_CONTEXT() of the global variables _AND_ of all the temporary variables that might have been generated in the accompagning initialisers is NULL_TREE, meaning the variables have been declared in the global namespace. @@ -3567,7 +3601,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp) /* When using __cxa_atexit, we never try to destroy anything from a static destructor. */ gcc_assert (initp); - guard_cond = get_guard_cond (guard); + guard_cond = get_guard_cond (guard, false); } /* If we don't have __cxa_atexit, then we will be running destructors from .fini sections, or their equivalents. So, @@ -3992,19 +4026,19 @@ cpp_check (tree t, cpp_operation op) /* Collect source file references recursively, starting from NAMESPC. */ -static void -collect_source_refs (tree namespc) +static void +collect_source_refs (tree namespc) { tree t; - if (!namespc) + if (!namespc) return; /* Iterate over names in this name space. */ for (t = NAMESPACE_LEVEL (namespc)->names; t; t = TREE_CHAIN (t)) if (!DECL_IS_BUILTIN (t) ) collect_source_ref (DECL_SOURCE_FILE (t)); - + /* Dump siblings, if any */ collect_source_refs (TREE_CHAIN (namespc)); @@ -4218,8 +4252,12 @@ handle_tls_init (void) one_static_initialization_or_destruction (var, init, true); #ifdef ASM_OUTPUT_DEF - /* Output init aliases even with -fno-extern-tls-init. */ - if (TREE_PUBLIC (var)) + /* Output init aliases even with -fno-extern-tls-init. Don't emit + aliases in LIPO aux modules, since the corresponding __tls_init + will be static promoted and deleted, so the variable's tls init + function will be resolved by its own primary module. An alias + would prevent the promoted aux __tls_init from being deleted. */ + if (TREE_PUBLIC (var) && !L_IPO_IS_AUXILIARY_MODULE) { tree single_init_fn = get_tls_init_fn (var); if (single_init_fn == NULL_TREE) @@ -4254,6 +4292,34 @@ dump_tu (void) } } +/* Much like the above, but not necessarily defined. 4.9 hack for setting + DECL_COMDAT on DECL_EXTERNAL functions, along with set_comdat. */ + +void +note_comdat_fn (tree decl) +{ + vec_safe_push (maybe_comdat_fns, decl); +} + +/* DECL is a function with vague linkage that was not + instantiated/synthesized in this translation unit. Set DECL_COMDAT for + the benefit of can_refer_decl_in_current_unit_p. */ + +static void +set_comdat (tree decl) +{ + DECL_COMDAT (decl) = true; + + tree clone; + FOR_EACH_CLONE (clone, decl) + set_comdat (clone); + + if (DECL_VIRTUAL_P (decl)) + for (tree thunk = DECL_THUNKS (decl); thunk; + thunk = DECL_CHAIN (thunk)) + DECL_COMDAT (thunk) = true; +} + /* This routine is called at the end of compilation. Its job is to create all the code needed to initialize and destroy the global aggregates. We do the destruction @@ -4603,6 +4669,8 @@ cp_write_global_declarations (void) bool reconsider = false; location_t locus; struct pointer_set_t *candidates; + size_t i; + tree decl; locus = input_location; at_eof = 1; @@ -4667,6 +4735,10 @@ cp_write_global_declarations (void) vtv_build_vtable_verify_fndecl (); } + FOR_EACH_VEC_SAFE_ELT (maybe_comdat_fns, i, decl) + if (!DECL_COMDAT (decl) && vague_linkage_p (decl)) + set_comdat (decl); + finalize_compilation_unit (); if (flag_vtable_verify) @@ -4941,7 +5013,7 @@ mark_used (tree decl, tsubst_flags_t complain) --function_depth; } - if (processing_template_decl) + if (processing_template_decl || in_template_function ()) return true; /* Check this too in case we're within fold_non_dependent_expr. */ |