gcc/cp/ * cp-objcp-common.c: Adjust comment for cxx_warn_unused_global_decl. * cp-objcp-common.h (LANG_HOOKS_WRITE_GLOBALS): Remove (LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS): New. * cp-tree.h (note_mangling_alias): Protoize. (cp_write_global_declarations): Remove. (cxx_post_compilation_parsing_cleanups): Protoize. * decl.c (wrapup_globals_for_namespace): Remove use of DATA argument. * decl2.c (mangling_aliases): New global. (build_java_method_aliases): New. Adapted from collect_candidates_for_java_method_aliases. (collect_candidates_for_java_method_aliases): Remove. (build_java_method_aliases): Remove. (generate_mangling_aliases): New. (note_mangling_alias): New. Moved from mangle_decl. (locus_at_end_of_parsing): New global. (c_parse_final_cleanups): Rename from cp_write_global_declarations. Use locus_at_end_of_parsing. Call generate_mangling_aliases. Rename call to collect_candidates_for_java_method_aliases into build_java_method_aliases. Remove call to finalize_compilation_unit. Move vtable handling into cxx_post_compilation_parsing_cleanups. Do not call check_global_declarations or emit_debug_global_declarations. (cxx_post_compilation_parsing_cleanups): New. * mangle.c (mangle_decl): Move code to note_mangling_alias. * name-lookup.c (do_namespace_alias): Call early_global_decl.
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index dd8e7c5..40b13ef 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -60,7 +60,7 @@ cxx_get_alias_set (tree t) return c_common_get_alias_set (t); } -/* Called from check_global_declarations. */ +/* Called from check_global_declaration. */ bool cxx_warn_unused_global_decl (const_tree decl) diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index 8a36e7f..c8572a7 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -84,8 +84,8 @@ extern void cp_common_init_ts (void); #define LANG_HOOKS_PRINT_ERROR_FUNCTION cxx_print_error_function #undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL cxx_warn_unused_global_decl -#undef LANG_HOOKS_WRITE_GLOBALS -#define LANG_HOOKS_WRITE_GLOBALS cp_write_global_declarations +#undef LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS +#define LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS cxx_post_compilation_parsing_cleanups #undef LANG_HOOKS_BUILTIN_FUNCTION #define LANG_HOOKS_BUILTIN_FUNCTION cxx_builtin_function #undef LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e0fbf5e..1998992 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5447,6 +5447,7 @@ extern tree finish_case_label (location_t, tree, tree); extern tree cxx_maybe_build_cleanup (tree, tsubst_flags_t); /* in decl2.c */ +extern void note_mangling_alias (tree, tree); extern bool check_java_method (tree); extern tree build_memfn_type (tree, tree, cp_cv_quals, cp_ref_qualifier); extern tree build_pointer_ptrmemfn_type (tree); @@ -5468,7 +5469,7 @@ extern tree cp_reconstruct_complex_type (tree, tree); extern bool attributes_naming_typedef_ok (tree); extern void cplus_decl_attributes (tree *, tree, int); extern void finish_anon_union (tree); -extern void cp_write_global_declarations (void); +extern void cxx_post_compilation_parsing_cleanups (void); extern tree coerce_new_type (tree); extern tree coerce_delete_type (tree); extern void comdat_linkage (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 6ec1579..dedf995 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -892,30 +892,19 @@ walk_namespaces (walk_namespaces_fn f, void* data) return walk_namespaces_r (global_namespace, f, data); } -/* Call wrapup_globals_declarations for the globals in NAMESPACE. If - DATA is non-NULL, this is the last time we will call - wrapup_global_declarations for this NAMESPACE. */ +/* Call wrapup_globals_declarations for the globals in NAMESPACE. */ int -wrapup_globals_for_namespace (tree name_space, void* data) +wrapup_globals_for_namespace (tree name_space, void* data ATTRIBUTE_UNUSED) { cp_binding_level *level = NAMESPACE_LEVEL (name_space); vec<tree, va_gc> *statics = level->static_decls; tree *vec = statics->address (); int len = statics->length (); - int last_time = (data != 0); - - if (last_time) - { - check_global_declarations (vec, len); - emit_debug_global_declarations (vec, len); - return 0; - } /* Write out any globals that need to be output. */ return wrapup_global_declarations (vec, len); } - /* In C++, you don't have to write `struct S' to refer to `S'; you can just use `S'. We accomplish this by creating a TYPE_DECL as diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index b2251d8..737db8c 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -118,6 +118,10 @@ static GTY(()) vec<tree, va_gc> *deferred_fns; sure are defined. */ static GTY(()) vec<tree, va_gc> *no_linkage_decls; +/* A vector of alternating decls and identifiers, where the latter + is to be an alias for the former if the former is defined. */ +static GTY(()) vec<tree, va_gc> *mangling_aliases; + /* Nonzero if we're done parsing and into end-of-file activities. */ int at_eof; @@ -3987,20 +3991,17 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data) } /* Java requires that we be able to reference a local address for a - method, and not be confused by PLT entries. If hidden aliases are - supported, collect and return all the functions for which we should - emit a hidden alias. */ + method, and not be confused by PLT entries. If supported, create a + hidden alias for all such methods. */ -static hash_set<tree> * -collect_candidates_for_java_method_aliases (void) +static void +build_java_method_aliases (void) { - struct cgraph_node *node; - hash_set<tree> *candidates = NULL; - #ifndef HAVE_GAS_HIDDEN - return candidates; + return; #endif + struct cgraph_node *node; FOR_EACH_FUNCTION (node) { tree fndecl = node->decl; @@ -4009,55 +4010,18 @@ collect_candidates_for_java_method_aliases (void) && TYPE_FOR_JAVA (DECL_CONTEXT (fndecl)) && TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl)) { - if (candidates == NULL) - candidates = new hash_set<tree>; - candidates->add (fndecl); - } - } - - return candidates; -} - - -/* Java requires that we be able to reference a local address for a - method, and not be confused by PLT entries. If hidden aliases are - supported, emit one for each java function that we've emitted. - CANDIDATES is the set of FUNCTION_DECLs that were gathered - by collect_candidates_for_java_method_aliases. */ - -static void -build_java_method_aliases (hash_set<tree> *candidates) -{ - struct cgraph_node *node; - -#ifndef HAVE_GAS_HIDDEN - return; -#endif - - FOR_EACH_FUNCTION (node) - { - tree fndecl = node->decl; - - if (TREE_ASM_WRITTEN (fndecl) - && candidates->contains (fndecl)) - { /* Mangle the name in a predictable way; we need to reference this from a java compiled object file. */ - tree oid, nid, alias; - const char *oname; - char *nname; - - oid = DECL_ASSEMBLER_NAME (fndecl); - oname = IDENTIFIER_POINTER (oid); + tree oid = DECL_ASSEMBLER_NAME (fndecl); + const char *oname = IDENTIFIER_POINTER (oid); gcc_assert (oname[0] == '_' && oname[1] == 'Z'); - nname = ACONCAT (("_ZGA", oname+2, NULL)); - nid = get_identifier (nname); + char *nname = ACONCAT (("_ZGA", oname + 2, NULL)); - alias = make_alias_for (fndecl, nid); + tree alias = make_alias_for (fndecl, get_identifier (nname)); TREE_PUBLIC (alias) = 1; DECL_VISIBILITY (alias) = VISIBILITY_HIDDEN; - assemble_alias (alias, oid); + cgraph_node::create_same_body_alias (alias, fndecl); } } } @@ -4318,6 +4282,66 @@ handle_tls_init (void) expand_or_defer_fn (finish_function (0)); } +/* We're at the end of compilation, so generate any mangling aliases that + we've been saving up, if DECL is going to be output and ID2 isn't + already taken by another declaration. */ + +static void +generate_mangling_alias (tree decl, tree id2) +{ + /* If there's a declaration already using this mangled name, + don't create a compatibility alias that conflicts. */ + if (IDENTIFIER_GLOBAL_VALUE (id2)) + return; + + struct cgraph_node *n = NULL; + if (TREE_CODE (decl) == FUNCTION_DECL + && !(n = cgraph_node::get (decl))) + /* Don't create an alias to an unreferenced function. */ + return; + + tree alias = make_alias_for (decl, id2); + SET_IDENTIFIER_GLOBAL_VALUE (id2, alias); + DECL_IGNORED_P (alias) = 1; + TREE_PUBLIC (alias) = TREE_PUBLIC (decl); + DECL_VISIBILITY (alias) = DECL_VISIBILITY (decl); + if (vague_linkage_p (decl)) + DECL_WEAK (alias) = 1; + if (TREE_CODE (decl) == FUNCTION_DECL) + n->create_same_body_alias (alias, decl); + else + varpool_node::create_extra_name_alias (alias, decl); +} + +/* Note that we might want to emit an alias with the symbol ID2 for DECL at + the end of translation, for compatibility across bugs in the mangling + implementation. */ + +void +note_mangling_alias (tree decl, tree id2) +{ +#ifdef ASM_OUTPUT_DEF + if (at_eof) + generate_mangling_alias (decl, id2); + else + { + vec_safe_push (mangling_aliases, decl); + vec_safe_push (mangling_aliases, id2); + } +#endif +} + +static void +generate_mangling_aliases () +{ + while (!vec_safe_is_empty (mangling_aliases)) + { + tree id2 = mangling_aliases->pop(); + tree decl = mangling_aliases->pop(); + generate_mangling_alias (decl, id2); + } +} + /* The entire file is now complete. If requested, dump everything to a file. */ @@ -4334,6 +4358,8 @@ dump_tu (void) } } +static location_t locus_at_end_of_parsing; + /* Check the deallocation functions for CODE to see if we want to warn that only one was defined. */ @@ -4381,18 +4407,16 @@ maybe_warn_sized_delete () first, since that way we only need to reverse the decls once. */ void -cp_write_global_declarations (void) +c_parse_final_cleanups (void) { tree vars; bool reconsider; size_t i; - location_t locus; unsigned ssdf_count = 0; int retries = 0; tree decl; - hash_set<tree> *candidates; - locus = input_location; + locus_at_end_of_parsing = input_location; at_eof = 1; /* Bad parse errors. Just forget about it. */ @@ -4424,6 +4448,7 @@ cp_write_global_declarations (void) /* FIXME - huh? was input_line -= 1;*/ + timevar_stop (TV_PHASE_PARSING); timevar_start (TV_PHASE_DEFERRED); /* We now have to write out all the stuff we put off writing out. @@ -4521,7 +4546,7 @@ cp_write_global_declarations (void) /* Set the line and file, so that it is obviously not from the source file. */ - input_location = locus; + input_location = locus_at_end_of_parsing; ssdf_body = start_static_storage_duration_function (ssdf_count); /* Make sure the back end knows about all the variables. */ @@ -4547,7 +4572,7 @@ cp_write_global_declarations (void) /* Finish up the static storage duration function for this round. */ - input_location = locus; + input_location = locus_at_end_of_parsing; finish_static_storage_duration_function (ssdf_body); /* All those initializations and finalizations might cause @@ -4555,7 +4580,7 @@ cp_write_global_declarations (void) instantiations, etc. */ reconsider = true; ssdf_count++; - /* ??? was: locus.line++; */ + /* ??? was: locus_at_end_of_parsing.line++; */ } /* Now do the same for thread_local variables. */ @@ -4679,6 +4704,8 @@ cp_write_global_declarations (void) } while (reconsider); + generate_mangling_aliases (); + /* All used inline functions must have a definition at this point. */ FOR_EACH_VEC_SAFE_ELT (deferred_fns, i, decl) { @@ -4696,7 +4723,7 @@ cp_write_global_declarations (void) (template_for_substitution (decl))))) { warning (0, "inline function %q+D used but never defined", decl); - /* Avoid a duplicate warning from check_global_declaration_1. */ + /* Avoid a duplicate warning from check_global_declaration. */ TREE_NO_WARNING (decl) = 1; } } @@ -4723,12 +4750,13 @@ cp_write_global_declarations (void) if (priority_info_map) splay_tree_foreach (priority_info_map, generate_ctor_and_dtor_functions_for_priority, - /*data=*/&locus); + /*data=*/&locus_at_end_of_parsing); else if (c_dialect_objc () && objc_static_init_needed_p ()) /* If this is obj-c++ and we need a static init, call generate_ctor_or_dtor_function. */ generate_ctor_or_dtor_function (/*constructor_p=*/true, - DEFAULT_INIT_PRIORITY, &locus); + DEFAULT_INIT_PRIORITY, + &locus_at_end_of_parsing); /* We're done with the splay-tree now. */ if (priority_info_map) @@ -4741,11 +4769,11 @@ cp_write_global_declarations (void) linkage now. */ pop_lang_context (); - /* Collect candidates for Java hidden aliases. */ - candidates = collect_candidates_for_java_method_aliases (); + /* Generate Java hidden aliases. */ + build_java_method_aliases (); timevar_stop (TV_PHASE_DEFERRED); - timevar_start (TV_PHASE_OPT_GEN); + timevar_start (TV_PHASE_PARSING); if (flag_vtable_verify) { @@ -4754,41 +4782,13 @@ cp_write_global_declarations (void) vtv_build_vtable_verify_fndecl (); } - symtab->finalize_compilation_unit (); - - if (flag_vtable_verify) - { - /* Generate the special constructor initialization function that - calls __VLTRegisterPairs, and give it a very high - initialization priority. This must be done after - finalize_compilation_unit so that we have accurate - information about which vtable will actually be emitted. */ - vtv_generate_init_routine (); - } - - timevar_stop (TV_PHASE_OPT_GEN); - timevar_start (TV_PHASE_CHECK_DBGINFO); - - /* Now, issue warnings about static, but not defined, functions, - etc., and emit debugging information. */ - walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider); - if (vec_safe_length (pending_statics) != 0) - { - check_global_declarations (pending_statics->address (), - pending_statics->length ()); - emit_debug_global_declarations (pending_statics->address (), - pending_statics->length ()); - } + /* Issue warnings about static, but not defined, functions, etc, and + generate initial debug information. */ + timevar_stop (TV_PHASE_PARSING); + timevar_start (TV_PHASE_DBGINFO); perform_deferred_noexcept_checks (); - /* Generate hidden aliases for Java. */ - if (candidates) - { - build_java_method_aliases (candidates); - delete candidates; - } - finish_repo (); /* The entire file is now complete. If requested, dump everything @@ -4800,13 +4800,37 @@ cp_write_global_declarations (void) dump_tree_statistics (); dump_time_statistics (); } - input_location = locus; + + timevar_stop (TV_PHASE_DBGINFO); + timevar_start (TV_PHASE_PARSING); +} + +/* Perform any post compilation-proper cleanups for the C++ front-end. + This should really go away. No front-end should need to do + anything past the compilation process. */ + +void +cxx_post_compilation_parsing_cleanups (void) +{ + timevar_start (TV_PHASE_LATE_PARSING_CLEANUPS); + + if (flag_vtable_verify) + { + /* Generate the special constructor initialization function that + calls __VLTRegisterPairs, and give it a very high + initialization priority. This must be done after + finalize_compilation_unit so that we have accurate + information about which vtable will actually be emitted. */ + vtv_generate_init_routine (); + } + + input_location = locus_at_end_of_parsing; #ifdef ENABLE_CHECKING validate_conversion_obstack (); #endif /* ENABLE_CHECKING */ - timevar_stop (TV_PHASE_CHECK_DBGINFO); + timevar_stop (TV_PHASE_LATE_PARSING_CLEANUPS); } /* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index b0f72d1..647ec70 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -3554,30 +3554,7 @@ mangle_decl (const tree decl) flag_abi_compat_version, id2); } -#ifdef ASM_OUTPUT_DEF - /* If there's a declaration already using this mangled name, - don't create a compatibility alias that conflicts. */ - if (IDENTIFIER_GLOBAL_VALUE (id2)) - return; - - struct cgraph_node *n = NULL; - if (TREE_CODE (decl) == FUNCTION_DECL - && !(n = cgraph_node::get (decl))) - /* Don't create an alias to an unreferenced function. */ - return; - - tree alias = make_alias_for (decl, id2); - SET_IDENTIFIER_GLOBAL_VALUE (id2, alias); - DECL_IGNORED_P (alias) = 1; - TREE_PUBLIC (alias) = TREE_PUBLIC (decl); - DECL_VISIBILITY (alias) = DECL_VISIBILITY (decl); - if (vague_linkage_p (decl)) - DECL_WEAK (alias) = 1; - if (TREE_CODE (decl) == FUNCTION_DECL) - n->create_same_body_alias (alias, decl); - else - varpool_node::create_extra_name_alias (alias, decl); -#endif + note_mangling_alias (decl, id2); } } diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 9e4e0e3..ebeb479 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -3899,7 +3899,7 @@ do_namespace_alias (tree alias, tree name_space) /* Emit debug info for namespace alias. */ if (!building_stmt_list_p ()) - (*debug_hooks->global_decl) (alias); + (*debug_hooks->early_global_decl) (alias); } /* Like pushdecl, only it places X in the current namespace,