[multiple changes]

2009-09-01  Diego Novillo  <dnovillo@google.com>

	* c-lang.c (lang_hooks): Remove const qualifier.

java/ChangeLog

	* lang.c (lang_hooks): Remove const qualifier.

objc/ChangeLog

	* objc-lang.c (lang_hooks): Remove const qualifier.

objcp/ChangeLog

	* objcp-lang.c (lang_hooks): Remove const qualifier.

ada/ChangeLog

	* gcc-interface/misc.c (lang_hooks): Remove const qualifier.

fortran/ChangeLog

	* f95-lang.c (lang_hooks): Remove const qualifier.

cp/ChangeLog

	* cp-lang.c (lang_hooks): Remove const qualifier.

2009-09-01  Diego Novillo  <dnovillo@google.com>

	* cgraph.c (cgraph_node_for_decl): New.
	* cgraph.h (cgraph_node_for_decl): Declare.
	* tree.c (host_integerp): Return 0 if T is NULL.


2009-09-01  Diego Novillo  <dnovillo@google.com>

	* tree.h (struct alias_pair): Move from varasm.c.
	(alias_pairs): Likewise.
	(TYPE_MAXVAL): Define.
	(TYPE_MINVAL): Define.
	(iterative_hash_host_wide_int): Declare.
	(remove_unreachable_alias_pairs): Declare.
	* tree-pass.h (pass_ipa_free_lang_data): Declare.
	* diagnostic.c (default_diagnostic_starter): Make extern.
	(default_diagnostic_finalizer): Make extern.
	* diagnostic.h (default_diagnostic_starter): Declare.
	(default_diagnostic_finalizer): Declare.
	(default_tree_printer): Declare.
	* toplev.c (default_tree_printer): Make extern.


2009-09-01  Richard Guenther  <rguenther@suse.de>
	    Diego Novillo  <dnovillo@google.com>

	* cgraph.c (cgraph_add_new_function): Remove gimplification.
	* cgraphunit.c (cgraph_expand_function): Do not emit
	associated thunks from here.
	(cgraph_emit_thunks): New.
	(cgraph_optimize): Call it.
	Return if any IPA pass finds an error.
	* varasm.c (finish_aliases_1): Ignore errorneous aliases used
	by thunks.


2009-09-01  Simon Baldwin  <simonb@google.com>
	    Rafael Espindola  <espindola@google.com>
	    Richard Guenther  <rguenther@suse.de>
	    Doug Kwan  <dougkwan@google.com>
	    Diego Novillo  <dnovillo@google.com>

	* tree.c: Include tree-pass.h, langhooks-def.h,
	diagnostic.h, cgraph.h, timevar.h, except.h and debug.h.
	(free_lang_data_in_type): New.
	(need_assembler_name_p): New.
	(free_lang_data_in_block): New.
	(free_lang_data_in_decl): New.
	(struct free_lang_data_d): New.
	(add_tree_to_fld_list): New.
	(find_decls_types_r): New.
	(get_eh_types_for_runtime): New.
	(find_decls_types_in_eh_region): New.
	(find_decls_types_in_node): New.
	(find_decls_types_in_var): New.
	(free_lang_data_in_cgraph): New.
	(free_lang_data): New.
	(gate_free_lang_data): New.
	(pass_ipa_free_lang_data): New.

2009-09-01  Diego Novillo  <dnovillo@google.com>

	* timevar.def (TV_IPA_FREE_LANG_DATA): Define.
	* langhooks.h (struct lang_hooks): Add field free_lang_data.
	(lang_hooks): Remove const qualifier.
	* ipa.c (cgraph_remove_unreachable_nodes): Call
	remove_unreachable_alias_pairs.
	* except.c (add_type_for_runtime): Check if TYPE has
	already been converted.
	(lookup_type_for_runtime): Likewise.
	(check_handled): Handle converted types.
	* varasm.c (remove_unreachable_alias_pairs): New.
	* gimple.c: Include demangle.h.
	(gimple_decl_printable_name): New.
	(gimple_fold_obj_type_ref): New.
	* gimple.h (gimple_decl_printable_name): Declare.
	(gimple_fold_obj_type_ref): Declare.
	* passes.c (init_optimization_passes): Add pass
	pass_ipa_free_lang_data.
	* langhooks-def.h (LANG_HOOKS_FREE_LANG_DATA): Define.
	(LANG_HOOKS_INITIALIZER): Add LANG_HOOKS_FREE_LANG_DATA.

testsuite/ChangeLog

2009-09-01  Diego Novillo  <dnovillo@google.com>

	* gcc.dg/gomp/combined-1.c: Adjust expected pattern.
	* g++.dg/tree-prof/inline_mismatch_args.C: Likewise.
	* g++.dg/warn/unit-1.C: Likewise.
	* g++.dg/ipa/iinline-1.C: Likewise.
	* g++.dg/template/cond2.C: Adjust expected line location for the
	error.
	* g++.dg/template/pr35240.C: Likewise.


cp/ChangeLog

2009-09-01  Doug Kwan  <dougkwan@google.com>

	* tree.c (cp_fix_function_decl_p): New.
	(cp_free_lang_data): New.

2009-09-01  Diego Novillo  <dnovillo@google.com>

	* Make-lang.in (decl2.o): Add dependency on $(POINTER_SET_H).
	* decl2.c: Include pointer-set.h.
	(collect_candidates_for_java_method_aliases): New.
	(cp_write_global_declarations): Call it.
	Add local variable CANDIDATES.  If set, call
	build_java_method_aliases.
	(build_java_method_aliases): Add argument CANDIDATES.
	Use it to determine if FNDECL should get a hidden alias.
	* cp-objcp-common.h (LANG_HOOKS_FREE_LANG_DATA): Define.
	* cp-tree.h (cp_free_lang_data): Declare.

2009-09-03  Richard Guenther  <rguenther@suse.de>

	* method.c (use_thunk): Use cgraph_finalize_function to hand
	off thunks to the cgraph.
	* semantics.c (emit_associated_thunks): Do not emit thunks
	for really extern functions.

From-SVN: r151360
This commit is contained in:
Diego Novillo 2009-09-03 00:07:12 -04:00
parent e25ea117b5
commit 4537ec0c86
46 changed files with 1319 additions and 62 deletions

View File

@ -1,3 +1,87 @@
2009-09-03 Diego Novillo <dnovillo@google.com>
* cgraph.c (cgraph_node_for_decl): New.
* cgraph.h (cgraph_node_for_decl): Declare.
* tree.c (host_integerp): Return 0 if T is NULL.
2009-09-03 Diego Novillo <dnovillo@google.com>
* tree.h (struct alias_pair): Move from varasm.c.
(alias_pairs): Likewise.
(TYPE_MAXVAL): Define.
(TYPE_MINVAL): Define.
(iterative_hash_host_wide_int): Declare.
(remove_unreachable_alias_pairs): Declare.
* tree-pass.h (pass_ipa_free_lang_data): Declare.
* diagnostic.c (default_diagnostic_starter): Make extern.
(default_diagnostic_finalizer): Make extern.
* diagnostic.h (default_diagnostic_starter): Declare.
(default_diagnostic_finalizer): Declare.
(default_tree_printer): Declare.
* toplev.c (default_tree_printer): Make extern.
2009-09-03 Richard Guenther <rguenther@suse.de>
Diego Novillo <dnovillo@google.com>
* cgraph.c (cgraph_add_new_function): Remove gimplification.
* cgraphunit.c (cgraph_expand_function): Do not emit
associated thunks from here.
(cgraph_emit_thunks): New.
(cgraph_optimize): Call it.
Return if any IPA pass finds an error.
* varasm.c (finish_aliases_1): Ignore errorneous aliases used
by thunks.
2009-09-03 Simon Baldwin <simonb@google.com>
Rafael Espindola <espindola@google.com>
Richard Guenther <rguenther@suse.de>
Doug Kwan <dougkwan@google.com>
Diego Novillo <dnovillo@google.com>
* tree.c: Include tree-pass.h, langhooks-def.h,
diagnostic.h, cgraph.h, timevar.h, except.h and debug.h.
(free_lang_data_in_type): New.
(need_assembler_name_p): New.
(free_lang_data_in_block): New.
(free_lang_data_in_decl): New.
(struct free_lang_data_d): New.
(add_tree_to_fld_list): New.
(find_decls_types_r): New.
(get_eh_types_for_runtime): New.
(find_decls_types_in_eh_region): New.
(find_decls_types_in_node): New.
(find_decls_types_in_var): New.
(free_lang_data_in_cgraph): New.
(free_lang_data): New.
(gate_free_lang_data): New.
(pass_ipa_free_lang_data): New.
2009-09-03 Diego Novillo <dnovillo@google.com>
* timevar.def (TV_IPA_FREE_LANG_DATA): Define.
* langhooks.h (struct lang_hooks): Add field free_lang_data.
(lang_hooks): Remove const qualifier.
* ipa.c (cgraph_remove_unreachable_nodes): Call
remove_unreachable_alias_pairs.
* except.c (add_type_for_runtime): Check if TYPE has
already been converted.
(lookup_type_for_runtime): Likewise.
(check_handled): Handle converted types.
* varasm.c (remove_unreachable_alias_pairs): New.
* gimple.c: Include demangle.h.
(gimple_decl_printable_name): New.
(gimple_fold_obj_type_ref): New.
* gimple.h (gimple_decl_printable_name): Declare.
(gimple_fold_obj_type_ref): Declare.
* passes.c (init_optimization_passes): Add pass
pass_ipa_free_lang_data.
* langhooks-def.h (LANG_HOOKS_FREE_LANG_DATA): Define.
(LANG_HOOKS_INITIALIZER): Add LANG_HOOKS_FREE_LANG_DATA.
2009-09-03 Diego Novillo <dnovillo@google.com>
* c-lang.c (lang_hooks): Remove const qualifier.
2009-09-02 Loren James Rittle <ljrittle@acm.org>
* doc/install.texi (*-*-freebsd*): Update target information.

View File

@ -2164,7 +2164,8 @@ tree.o : tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
all-tree.def $(FLAGS_H) $(FUNCTION_H) $(PARAMS_H) \
$(TOPLEV_H) $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H) langhooks.h \
$(REAL_H) gt-tree.h $(TREE_INLINE_H) tree-iterator.h $(BASIC_BLOCK_H) \
$(TREE_FLOW_H) $(OBSTACK_H) pointer-set.h fixed-value.h
$(TREE_FLOW_H) $(OBSTACK_H) pointer-set.h fixed-value.h tree-pass.h \
langhooks-def.h $(DIAGNOSTIC_H) $(CGRAPH_H) $(TIMEVAR_H) except.h debug.h
tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(TOPLEV_H) $(SPLAY_TREE_H) $(TREE_DUMP_H) \
tree-iterator.h $(TREE_PASS_H) $(DIAGNOSTIC_H) $(REAL_H) fixed-value.h

View File

@ -1,3 +1,7 @@
2009-09-03 Diego Novillo <dnovillo@google.com>
* gcc-interface/misc.c (lang_hooks): Remove const qualifier.
2009-09-02 Richard Henderson <rth@redhat.com>
* tb-gcc.c (__gnat_backtrace): Mark all arguments unused.

View File

@ -131,7 +131,7 @@ static void gnat_get_subrange_bounds (const_tree, tree *, tree *);
#undef LANG_HOOKS_BUILTIN_FUNCTION
#define LANG_HOOKS_BUILTIN_FUNCTION gnat_builtin_function
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
/* How much we want of our DWARF extensions. Some of our dwarf+ extensions
are incompatible with regular GDB versions, so we must make sure to only

View File

@ -46,7 +46,7 @@ enum c_language_kind c_language = clk_c;
#define LANG_HOOKS_INIT c_objc_common_init
/* Each front end provides its own lang hook initializer. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
/* Final processing of file-scope data. The Objective-C version of
this function still does something. */

View File

@ -404,6 +404,33 @@ hash_node (const void *p)
return (hashval_t) DECL_UID (n->decl);
}
/* Return the cgraph node associated with function DECL. If none
exists, return NULL. */
struct cgraph_node *
cgraph_node_for_decl (tree decl)
{
struct cgraph_node *node;
void **slot;
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
node = NULL;
if (cgraph_hash)
{
struct cgraph_node key;
key.decl = decl;
slot = htab_find_slot (cgraph_hash, &key, NO_INSERT);
if (slot && *slot)
node = (struct cgraph_node *) *slot;
}
return node;
}
/* Returns nonzero if P1 and P2 are equal. */
static int
@ -1893,9 +1920,6 @@ cgraph_add_new_function (tree fndecl, bool lowered)
push_cfun (DECL_STRUCT_FUNCTION (fndecl));
current_function_decl = fndecl;
gimple_register_cfg_hooks ();
/* C++ Thunks are emitted late via this function, gimplify them. */
if (!gimple_body (fndecl))
gimplify_function_tree (fndecl);
tree_lowering_passes (fndecl);
bitmap_obstack_initialize (NULL);
if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))

View File

@ -391,7 +391,8 @@ struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
struct cgraph_node * cgraph_get_node (tree);
struct cgraph_node *cgraph_node (tree);
struct cgraph_node *cgraph_node_for_asm (tree asmname);
struct cgraph_node *cgraph_node_for_asm (tree);
struct cgraph_node *cgraph_node_for_decl (tree);
struct cgraph_edge *cgraph_edge (struct cgraph_node *, gimple);
void cgraph_set_call_stmt (struct cgraph_edge *, gimple);
void cgraph_set_call_stmt_including_clones (struct cgraph_node *, gimple, gimple);

View File

@ -1108,9 +1108,6 @@ cgraph_expand_function (struct cgraph_node *node)
gcc_assert (node->lowered);
/* Generate RTL for the body of DECL. */
if (lang_hooks.callgraph.emit_associated_thunks
&& node->finalized_by_frontend)
lang_hooks.callgraph.emit_associated_thunks (decl);
tree_rest_of_compilation (decl);
/* Make sure that BE didn't give up on compiling. */
@ -1324,6 +1321,30 @@ ipa_passes (void)
bitmap_obstack_release (NULL);
}
/* Emit thunks for every node in the cgraph.
FIXME: We really ought to emit thunks only for functions that are needed. */
static void
cgraph_emit_thunks (void)
{
struct cgraph_node *n;
for (n = cgraph_nodes; n; n = n->next)
{
/* Only emit thunks on functions defined in this TU.
Note that this may emit more thunks than strictly necessary.
During optimization some nodes may disappear. It would be
nice to only emit thunks only for the functions that will be
emitted, but we cannot know that until the inliner and other
IPA passes have run (see the sequencing of the call to
cgraph_mark_functions_to_output in cgraph_optimize). */
if (!DECL_EXTERNAL (n->decl))
lang_hooks.callgraph.emit_associated_thunks (n->decl);
}
}
/* Perform simple optimizations based on callgraph. */
static void
@ -1336,6 +1357,14 @@ cgraph_optimize (void)
verify_cgraph ();
#endif
/* Emit thunks, if needed. */
if (lang_hooks.callgraph.emit_associated_thunks)
{
cgraph_emit_thunks ();
if (errorcount || sorrycount)
return;
}
/* Call functions declared with the "constructor" or "destructor"
attribute. */
cgraph_build_cdtor_fns ();
@ -1359,6 +1388,10 @@ cgraph_optimize (void)
if (errorcount == 0 && sorrycount == 0)
ipa_passes ();
/* Do nothing else if any IPA pass found errors. */
if (errorcount || sorrycount)
return;
/* This pass remove bodies of extern inline functions we never inlined.
Do this later so other IPA passes see what is really going on. */
cgraph_remove_unreachable_nodes (false, dump_file);
@ -1428,6 +1461,8 @@ cgraph_optimize (void)
}
#endif
}
/* Generate and emit a static constructor or destructor. WHICH must
be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the

View File

@ -1,3 +1,32 @@
2009-09-03 Doug Kwan <dougkwan@google.com>
* tree.c (cp_fix_function_decl_p): New.
(cp_free_lang_data): New.
2009-09-03 Diego Novillo <dnovillo@google.com>
* Make-lang.in (decl2.o): Add dependency on $(POINTER_SET_H).
* decl2.c: Include pointer-set.h.
(collect_candidates_for_java_method_aliases): New.
(cp_write_global_declarations): Call it.
Add local variable CANDIDATES. If set, call
build_java_method_aliases.
(build_java_method_aliases): Add argument CANDIDATES.
Use it to determine if FNDECL should get a hidden alias.
* cp-objcp-common.h (LANG_HOOKS_FREE_LANG_DATA): Define.
* cp-tree.h (cp_free_lang_data): Declare.
2009-09-03 Richard Guenther <rguenther@suse.de>
* method.c (use_thunk): Use cgraph_finalize_function to hand
off thunks to the cgraph.
* semantics.c (emit_associated_thunks): Do not emit thunks
for really extern functions.
2009-09-03 Diego Novillo <dnovillo@google.com>
* cp-lang.c (lang_hooks): Remove const qualifier.
2009-09-02 Jason Merrill <jason@redhat.com>
* semantics.c (describable_type): Don't pretend to be in a template.

View File

@ -257,7 +257,7 @@ cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h \
debug.h gt-cp-decl.h $(TIMEVAR_H) $(TREE_FLOW_H) $(TARGET_H) $(PLUGIN_H)
cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h $(EXPR_H) \
output.h except.h toplev.h $(RTL_H) $(C_COMMON_H) gt-cp-decl2.h $(CGRAPH_H) \
$(C_PRAGMA_H) $(TREE_DUMP_H) intl.h $(TARGET_H) $(GIMPLE_H)
$(C_PRAGMA_H) $(TREE_DUMP_H) intl.h $(TARGET_H) $(GIMPLE_H) $(POINTER_SET_H)
cp/cp-objcp-common.o : cp/cp-objcp-common.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(TREE_H) $(CXX_TREE_H) $(C_COMMON_H) toplev.h \
langhooks.h $(LANGHOOKS_DEF_H) $(DIAGNOSTIC_H) debug.h \

View File

@ -73,7 +73,7 @@ static enum classify_record cp_classify_record (tree type);
#define LANG_HOOKS_INIT_TS cp_init_ts
/* Each front end provides its own lang hook initializer. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
/* Lang hook routines common to C++ and ObjC++ appear in cp/cp-objcp-common.c;
there should be very few routines below. */

View File

@ -32,6 +32,8 @@ extern bool cp_function_decl_explicit_p (tree decl);
specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c,
respectively. */
#undef LANG_HOOKS_FREE_LANG_DATA
#define LANG_HOOKS_FREE_LANG_DATA cp_free_lang_data
#undef LANG_HOOKS_TREE_SIZE
#define LANG_HOOKS_TREE_SIZE cp_tree_size
#undef LANG_HOOKS_FINISH

View File

@ -4891,6 +4891,7 @@ extern tree finish_decltype_type (tree, bool);
extern tree finish_trait_expr (enum cp_trait_kind, tree, tree);
/* in tree.c */
void cp_free_lang_data (tree t);
extern tree force_target_expr (tree, tree);
extern tree build_target_expr_with_type (tree, tree);
extern void lang_check_failed (const char *, int,

View File

@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-dump.h"
#include "intl.h"
#include "gimple.h"
#include "pointer-set.h"
extern cpp_reader *parse_in;
@ -3288,10 +3289,46 @@ cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED)
/* 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. */
supported, collect and return all the functions for which we should
emit a hidden alias. */
static struct pointer_set_t *
collect_candidates_for_java_method_aliases (void)
{
struct cgraph_node *node;
struct pointer_set_t *candidates = NULL;
#ifndef HAVE_GAS_HIDDEN
return candidates;
#endif
for (node = cgraph_nodes; node ; node = node->next)
{
tree fndecl = node->decl;
if (DECL_CONTEXT (fndecl)
&& TYPE_P (DECL_CONTEXT (fndecl))
&& TYPE_FOR_JAVA (DECL_CONTEXT (fndecl))
&& TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl))
{
if (candidates == NULL)
candidates = pointer_set_create ();
pointer_set_insert (candidates, 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 (void)
build_java_method_aliases (struct pointer_set_t *candidates)
{
struct cgraph_node *node;
@ -3304,10 +3341,7 @@ build_java_method_aliases (void)
tree fndecl = node->decl;
if (TREE_ASM_WRITTEN (fndecl)
&& DECL_CONTEXT (fndecl)
&& TYPE_P (DECL_CONTEXT (fndecl))
&& TYPE_FOR_JAVA (DECL_CONTEXT (fndecl))
&& TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl))
&& pointer_set_contains (candidates, fndecl))
{
/* Mangle the name in a predictable way; we need to reference
this from a java compiled object file. */
@ -3379,6 +3413,7 @@ cp_write_global_declarations (void)
unsigned ssdf_count = 0;
int retries = 0;
tree decl;
struct pointer_set_t *candidates;
locus = input_location;
at_eof = 1;
@ -3676,6 +3711,9 @@ cp_write_global_declarations (void)
linkage now. */
pop_lang_context ();
/* Collect candidates for Java hidden aliases. */
candidates = collect_candidates_for_java_method_aliases ();
cgraph_finalize_compilation_unit ();
/* Now, issue warnings about static, but not defined, functions,
@ -3690,7 +3728,11 @@ cp_write_global_declarations (void)
}
/* Generate hidden aliases for Java. */
build_java_method_aliases ();
if (candidates)
{
build_java_method_aliases (candidates);
pointer_set_destroy (candidates);
}
finish_repo ();

View File

@ -3186,7 +3186,9 @@ emit_associated_thunks (tree fn)
is so that you can know statically the entire set of thunks that
will ever be needed for a given virtual function, thereby
enabling you to output all the thunks with the function itself. */
if (DECL_VIRTUAL_P (fn))
if (DECL_VIRTUAL_P (fn)
/* Do not emit thunks for extern template instantiations. */
&& ! DECL_REALLY_EXTERN (fn))
{
tree thunk;

View File

@ -3030,6 +3030,53 @@ cast_valid_in_integral_constant_expression_p (tree type)
|| type == error_mark_node);
}
/* Return true if we need to fix linkage information of DECL. */
static bool
cp_fix_function_decl_p (tree decl)
{
/* Skip if DECL is not externally visible. */
if (!TREE_PUBLIC (decl))
return false;
/* We need to fix DECL if it a appears to be exported but with no
function body. Thunks do not have CFGs and we may need to
handle them specially later. */
if (!gimple_has_body_p (decl)
&& !DECL_THUNK_P (decl)
&& !DECL_EXTERNAL (decl))
return true;
return false;
}
/* Clean the C++ specific parts of the tree T. */
void
cp_free_lang_data (tree t)
{
if (TREE_CODE (t) == METHOD_TYPE
|| TREE_CODE (t) == FUNCTION_TYPE)
{
/* Default args are not interesting anymore. */
tree argtypes = TYPE_ARG_TYPES (t);
while (argtypes)
{
TREE_PURPOSE (argtypes) = 0;
argtypes = TREE_CHAIN (argtypes);
}
}
else if (TREE_CODE (t) == FUNCTION_DECL
&& cp_fix_function_decl_p (t))
{
/* If T is used in this translation unit at all, the definition
must exist somewhere else since we have decided to not emit it
in this TU. So make it an external reference. */
DECL_EXTERNAL (t) = 1;
TREE_STATIC (t) = 0;
}
}
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
/* Complain that some language-specific thing hanging off a tree

View File

@ -48,11 +48,6 @@ along with GCC; see the file COPYING3. If not see
/* Prototypes. */
static char *build_message_string (const char *, ...) ATTRIBUTE_PRINTF_1;
static void default_diagnostic_starter (diagnostic_context *,
diagnostic_info *);
static void default_diagnostic_finalizer (diagnostic_context *,
diagnostic_info *);
static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
static void diagnostic_action_after_output (diagnostic_context *,
@ -266,7 +261,7 @@ diagnostic_report_current_module (diagnostic_context *context)
}
}
static void
void
default_diagnostic_starter (diagnostic_context *context,
diagnostic_info *diagnostic)
{
@ -274,7 +269,7 @@ default_diagnostic_starter (diagnostic_context *context,
pp_set_prefix (context->printer, diagnostic_build_prefix (diagnostic));
}
static void
void
default_diagnostic_finalizer (diagnostic_context *context,
diagnostic_info *diagnostic ATTRIBUTE_UNUSED)
{

View File

@ -213,6 +213,8 @@ extern bool emit_diagnostic (diagnostic_t, location_t, int,
const char *, ...) ATTRIBUTE_GCC_DIAG(4,5);
#endif
extern char *diagnostic_build_prefix (diagnostic_info *);
void default_diagnostic_starter (diagnostic_context *, diagnostic_info *);
void default_diagnostic_finalizer (diagnostic_context *, diagnostic_info *);
/* Pure text formatting support functions. */
extern char *file_name_as_prefix (const char *);
@ -239,4 +241,8 @@ extern void print_gimple_stmt (FILE *, gimple, int, int);
extern void print_gimple_expr (FILE *, gimple, int, int);
extern void dump_gimple_stmt (pretty_printer *, gimple, int, int);
/* In toplev.c */
extern bool default_tree_printer (pretty_printer *, text_info *, const char *,
int, bool, bool, bool);
#endif /* ! GCC_DIAGNOSTIC_H */

View File

@ -1688,6 +1688,10 @@ add_type_for_runtime (tree type)
{
tree *slot;
/* If TYPE is NOP_EXPR, it means that it already is a runtime type. */
if (TREE_CODE (type) == NOP_EXPR)
return;
slot = (tree *) htab_find_slot_with_hash (type_to_runtime_map, type,
TREE_HASH (type), INSERT);
if (*slot == NULL)
@ -1702,6 +1706,10 @@ lookup_type_for_runtime (tree type)
{
tree *slot;
/* If TYPE is NOP_EXPR, it means that it already is a runtime type. */
if (TREE_CODE (type) == NOP_EXPR)
return type;
slot = (tree *) htab_find_slot_with_hash (type_to_runtime_map, type,
TREE_HASH (type), NO_INSERT);
@ -2881,8 +2889,33 @@ check_handled (tree handled, tree type)
if (! lang_eh_type_covers)
{
for (t = handled; t ; t = TREE_CHAIN (t))
if (TREE_VALUE (t) == type)
return 1;
{
tree t1 = TREE_VALUE (t);
tree t2 = type;
/* If the types have been converted to runtime types (i.e.,
when the IL is being read from disk in an LTO
compilation), then T1 and T2 will be pointers to the
runtime type of the form '(void *) &<runtime_type>' (See
cp/except.c:build_eh_type_type). Strip the conversion
and the address. */
if (CONVERT_EXPR_P (t1))
{
STRIP_NOPS (t1);
gcc_assert (TREE_CODE (t1) == ADDR_EXPR);
t1 = TREE_OPERAND (t1, 0);
}
if (CONVERT_EXPR_P (t2))
{
STRIP_NOPS (t2);
gcc_assert (TREE_CODE (t2) == ADDR_EXPR);
t2 = TREE_OPERAND (t2, 0);
}
if (t1 == t2)
return 1;
}
}
else
{

View File

@ -1,3 +1,7 @@
2009-09-03 Diego Novillo <dnovillo@google.com>
* f95-lang.c (lang_hooks): Remove const qualifier.
2009-09-01 Richard Guenther <rguenther@suse.de>
* f95-lang.c (gfc_mark_addressable): Remove.

View File

@ -154,7 +154,7 @@ static void gfc_init_ts (void);
#define LANG_HOOKS_BUILTIN_FUNCTION gfc_builtin_function
#define LANG_HOOKS_GET_ARRAY_DESCR_INFO gfc_get_array_descr_info
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
#define NULL_BINDING_LEVEL (struct binding_level *) NULL

View File

@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-flow.h"
#include "value-prof.h"
#include "flags.h"
#include "demangle.h"
#define DEFGSCODE(SYM, NAME, STRUCT) NAME,
const char *const gimple_code_name[] = {
@ -3427,4 +3428,75 @@ gimple_ior_addresses_taken (bitmap addresses_taken, gimple stmt)
gimple_ior_addresses_taken_1);
}
/* Return a printable name for symbol DECL. */
const char *
gimple_decl_printable_name (tree decl, int verbosity)
{
gcc_assert (decl && DECL_NAME (decl));
if (DECL_ASSEMBLER_NAME_SET_P (decl))
{
const char *str, *mangled_str;
int dmgl_opts = DMGL_NO_OPTS;
if (verbosity >= 2)
{
dmgl_opts = DMGL_VERBOSE
| DMGL_TYPES
| DMGL_ANSI
| DMGL_GNU_V3
| DMGL_RET_POSTFIX;
if (TREE_CODE (decl) == FUNCTION_DECL)
dmgl_opts |= DMGL_PARAMS;
}
mangled_str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
str = cplus_demangle_v3 (mangled_str, dmgl_opts);
return (str) ? str : mangled_str;
}
return IDENTIFIER_POINTER (DECL_NAME (decl));
}
/* Fold a OBJ_TYPE_REF expression to the address of a function.
KNOWN_TYPE carries the true type of OBJ_TYPE_REF_OBJECT(REF). Adapted
from cp_fold_obj_type_ref, but it tolerates types with no binfo
data. */
tree
gimple_fold_obj_type_ref (tree ref, tree known_type)
{
HOST_WIDE_INT index;
HOST_WIDE_INT i;
tree v;
tree fndecl;
if (TYPE_BINFO (known_type) == NULL_TREE)
return NULL_TREE;
v = BINFO_VIRTUALS (TYPE_BINFO (known_type));
index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
i = 0;
while (i != index)
{
i += (TARGET_VTABLE_USES_DESCRIPTORS
? TARGET_VTABLE_USES_DESCRIPTORS : 1);
v = TREE_CHAIN (v);
}
fndecl = TREE_VALUE (v);
#ifdef ENABLE_CHECKING
gcc_assert (tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref),
DECL_VINDEX (fndecl)));
#endif
cgraph_node (fndecl)->local.vtable_method = true;
return build_fold_addr_expr (fndecl);
}
#include "gt-gimple.h"

View File

@ -836,6 +836,8 @@ bool gimple_assign_rhs_could_trap_p (gimple);
void gimple_regimplify_operands (gimple, gimple_stmt_iterator *);
bool empty_body_p (gimple_seq);
unsigned get_gimple_rhs_num_ops (enum tree_code);
const char *gimple_decl_printable_name (tree, int);
tree gimple_fold_obj_type_ref (tree, tree);
/* Returns true iff T is a valid GIMPLE statement. */
extern bool is_gimple_stmt (tree);

View File

@ -240,6 +240,11 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
#ifdef ENABLE_CHECKING
verify_cgraph ();
#endif
/* Reclaim alias pairs for functions that have disappeared from the
call graph. */
remove_unreachable_alias_pairs ();
return changed;
}

View File

@ -1,3 +1,7 @@
2009-09-03 Diego Novillo <dnovillo@google.com>
* lang.c (lang_hooks): Remove const qualifier.
2009-09-01 Jakub Jelinek <jakub@redhat.com>
* boehm.c (mark_reference_fields): Compute % in HOST_WIDE_INT

View File

@ -159,7 +159,7 @@ struct GTY(()) language_function {
#define LANG_HOOKS_ATTRIBUTE_TABLE java_attribute_table
/* Each front end provides its own. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
/*
* process java-specific compiler command-line options

View File

@ -99,6 +99,7 @@ extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *,
#define LANG_HOOKS_PRINT_ERROR_FUNCTION lhd_print_error_function
#define LANG_HOOKS_DECL_PRINTABLE_NAME lhd_decl_printable_name
#define LANG_HOOKS_DWARF_NAME lhd_dwarf_name
#define LANG_HOOKS_FREE_LANG_DATA lhd_do_nothing_t
#define LANG_HOOKS_TREE_SIZE lhd_tree_size
#define LANG_HOOKS_TYPES_COMPATIBLE_P lhd_types_compatible_p
#define LANG_HOOKS_BUILTIN_FUNCTION lhd_builtin_function
@ -229,6 +230,7 @@ extern tree lhd_make_node (enum tree_code);
#define LANG_HOOKS_INITIALIZER { \
LANG_HOOKS_NAME, \
LANG_HOOKS_IDENTIFIER_SIZE, \
LANG_HOOKS_FREE_LANG_DATA, \
LANG_HOOKS_TREE_SIZE, \
LANG_HOOKS_INIT_OPTIONS, \
LANG_HOOKS_INITIALIZE_DIAGNOSTICS, \

View File

@ -235,6 +235,9 @@ struct lang_hooks
identifier nodes long enough for the language-specific slots. */
size_t identifier_size;
/* Remove any parts of the tree that are used only by the FE. */
void (*free_lang_data) (tree);
/* Determines the size of any language-specific tcc_constant or
tcc_exceptional nodes. Since it is called from make_node, the
only information available is the tree code. Expected to die
@ -416,7 +419,7 @@ struct lang_hooks
};
/* Each front end provides its own. */
extern const struct lang_hooks lang_hooks;
extern struct lang_hooks lang_hooks;
extern tree add_builtin_function (const char *name, tree type,
int function_code, enum built_in_class cl,
const char *library_name,

View File

@ -1,3 +1,7 @@
2009-09-03 Diego Novillo <dnovillo@google.com>
* objc-lang.c (lang_hooks): Remove const qualifier.
2009-08-20 Richard Guenther <rguenther@suse.de>
* objc-act.c: Include c-lang.h

View File

@ -52,7 +52,7 @@ static void objc_init_ts (void);
#define LANG_HOOKS_INIT_TS objc_init_ts
/* Each front end provides its own lang hook initializer. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
/* Lang hook routines common to C and ObjC appear in c-objc-common.c;
there should be very few (if any) routines below. */

View File

@ -1,3 +1,7 @@
2009-09-03 Diego Novillo <dnovillo@google.com>
* objcp-lang.c (lang_hooks): Remove const qualifier.
2009-07-14 Taras Glek <tglek@mozilla.com>
Rafael Espindola <espindola@google.com>

View File

@ -52,7 +52,7 @@ static void objcxx_init_ts (void);
#define LANG_HOOKS_INIT_TS objcxx_init_ts
/* Each front end provides its own lang hook initializer. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
/* Lang hook routines common to C++ and ObjC++ appear in cp/cp-objcp-common.c;
there should be very few (if any) routines below. */

View File

@ -535,6 +535,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_inline_parameters);
NEXT_PASS (pass_rebuild_cgraph_edges);
}
NEXT_PASS (pass_ipa_free_lang_data);
NEXT_PASS (pass_early_local_passes);
{
struct opt_pass **p = &pass_early_local_passes.pass.sub;

View File

@ -1,3 +1,13 @@
2009-09-03 Diego Novillo <dnovillo@google.com>
* gcc.dg/gomp/combined-1.c: Adjust expected pattern.
* g++.dg/tree-prof/inline_mismatch_args.C: Likewise.
* g++.dg/warn/unit-1.C: Likewise.
* g++.dg/ipa/iinline-1.C: Likewise.
* g++.dg/template/cond2.C: Adjust expected line location for the
error.
* g++.dg/template/pr35240.C: Likewise.
2009-09-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.dg/tree-ssa/inline-3.c: Add -fpie when pic.

View File

@ -44,5 +44,5 @@ int main (int argc, char *argv[])
return 0;
}
/* { dg-final { scan-ipa-dump "String::funcOne\[^\\n\]*inline copy in int main" "inline" } } */
/* { dg-final { scan-ipa-dump "String::funcOne\[^\\n\]*inline copy in main" "inline" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */

View File

@ -3,8 +3,8 @@
template<int X> class c;
template<int X, int Y> int test(c<X ? : Y>&);
template<int X, int Y> int test(c<X ? : Y>&); // { dg-error "omitted" }
void test(c<2>*c2) {
test<0, 2>(*c2); // { dg-error "omitted" }
test<0, 2>(*c2);
}

View File

@ -4,9 +4,9 @@
template<int> struct A {};
template<int N> A<sizeof(new int[N][N])> foo();
template<int N> A<sizeof(new int[N][N])> foo(); // { dg-message "unimplemented" }
void bar()
{
foo<1>(); // { dg-message "unimplemented" }
foo<1>();
}

View File

@ -31,6 +31,6 @@ int main(void)
baz.Bar(&baz, gid);
return 0;
}
/* { dg-final-use { scan-tree-dump "Inlining virtual void Super::Foo" "einline2"} } */
/* { dg-final-use { scan-tree-dump "Inlining .*Super::Foo" "einline2"} } */
/* { dg-final-use { scan-tree-dump-not "mismatched arguments" "einline2"} } */
/* { dg-final-use { cleanup-tree-dump "einline2" } } */

View File

@ -4,7 +4,7 @@
struct a { int mode; };
int sys_msgctl (void)
{
struct a setbuf; /* { dg-warning "'setbuf\.a::mode' is used" "" { xfail *-*-* } } */
struct a setbuf; /* { dg-warning "'setbuf.mode' is used" "" { xfail *-*-* } } */
return setbuf.mode;
}

View File

@ -20,5 +20,5 @@ int foo (void)
}
}
/* { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel_loop_runtime_start" 3 "optimized" } } */
/* { dg-final { scan-tree-dump-times "GOMP_parallel_loop_runtime_start" 3 "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */

View File

@ -46,6 +46,7 @@ DEFTIMEVAR (TV_IPA_REFERENCE , "ipa reference")
DEFTIMEVAR (TV_IPA_PURE_CONST , "ipa pure const")
DEFTIMEVAR (TV_IPA_TYPE_ESCAPE , "ipa type escape")
DEFTIMEVAR (TV_IPA_PTA , "ipa points-to")
DEFTIMEVAR (TV_IPA_FREE_LANG_DATA , "ipa free lang data")
/* Time spent by constructing CFG. */
DEFTIMEVAR (TV_CFG , "cfg construction")
/* Time spent by cleaning up CFG. */

View File

@ -1576,8 +1576,8 @@ default_pch_valid_p (const void *data_p, size_t len)
}
/* Default tree printer. Handles declarations only. */
static bool
default_tree_printer (pretty_printer * pp, text_info *text, const char *spec,
bool
default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
int precision, bool wide, bool set_locus, bool hash)
{
tree t;

View File

@ -409,6 +409,7 @@ extern struct gimple_opt_pass pass_warn_unused_result;
/* IPA Passes */
extern struct ipa_opt_pass_d pass_ipa_inline;
extern struct simple_ipa_opt_pass pass_ipa_free_lang_data;
extern struct ipa_opt_pass_d pass_ipa_cp;
extern struct ipa_opt_pass_d pass_ipa_reference;
extern struct ipa_opt_pass_d pass_ipa_pure_const;

View File

@ -52,6 +52,13 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "pointer-set.h"
#include "fixed-value.h"
#include "tree-pass.h"
#include "langhooks-def.h"
#include "diagnostic.h"
#include "cgraph.h"
#include "timevar.h"
#include "except.h"
#include "debug.h"
/* Tree code classes. */
@ -4124,6 +4131,789 @@ build_type_attribute_variant (tree ttype, tree attribute)
TYPE_QUALS (ttype));
}
/* Reset all language specific information still present in TYPE. */
static void
free_lang_data_in_type (tree type)
{
gcc_assert (TYPE_P (type));
/* Fill in the alias-set. We need to at least track zeroness here
for correctness. */
if (lang_hooks.get_alias_set (type) == 0)
TYPE_ALIAS_SET (type) = 0;
/* Give the FE a chance to remove its own data first. */
lang_hooks.free_lang_data (type);
TREE_LANG_FLAG_0 (type) = 0;
TREE_LANG_FLAG_1 (type) = 0;
TREE_LANG_FLAG_2 (type) = 0;
TREE_LANG_FLAG_3 (type) = 0;
TREE_LANG_FLAG_4 (type) = 0;
TREE_LANG_FLAG_5 (type) = 0;
TREE_LANG_FLAG_6 (type) = 0;
if (TREE_CODE (type) == FUNCTION_TYPE)
{
/* Remove the const and volatile qualifiers from arguments. The
C++ front end removes them, but the C front end does not,
leading to false ODR violation errors when merging two
instances of the same function signature compiled by
different front ends. */
tree p;
for (p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
{
tree arg_type = TREE_VALUE (p);
if (TYPE_READONLY (arg_type) || TYPE_VOLATILE (arg_type))
{
int quals = TYPE_QUALS (arg_type)
& ~TYPE_QUAL_CONST
& ~TYPE_QUAL_VOLATILE;
TREE_VALUE (p) = build_qualified_type (arg_type, quals);
free_lang_data_in_type (TREE_VALUE (p));
}
}
}
/* Remove members that are not actually FIELD_DECLs from the field
list of an aggregate. These occur in C++. */
if (TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE)
{
tree prev, member;
/* Note that TYPE_FIELDS can be shared across distinct
TREE_TYPEs. Therefore, if the first field of TYPE_FIELDS is
to be removed, we cannot set its TREE_CHAIN to NULL.
Otherwise, we would not be able to find all the other fields
in the other instances of this TREE_TYPE.
This was causing an ICE in testsuite/g++.dg/lto/20080915.C. */
prev = NULL_TREE;
member = TYPE_FIELDS (type);
while (member)
{
if (TREE_CODE (member) == FIELD_DECL)
{
if (prev)
TREE_CHAIN (prev) = member;
else
TYPE_FIELDS (type) = member;
prev = member;
}
member = TREE_CHAIN (member);
}
if (prev)
TREE_CHAIN (prev) = NULL_TREE;
else
TYPE_FIELDS (type) = NULL_TREE;
TYPE_METHODS (type) = NULL_TREE;
if (TYPE_BINFO (type))
{
tree binfo = TYPE_BINFO (type);
if (BINFO_VIRTUALS (binfo))
{
/* If the virtual function table for BINFO contains
entries, these may be useful for folding OBJ_TYPE_REF
expressions (see gimple_fold_obj_type_ref). In that
case, we only clear the unused fields in the BINFO
structure. */
BINFO_OFFSET (binfo) = NULL_TREE;
BINFO_VTABLE (binfo) = NULL_TREE;
BINFO_VPTR_FIELD (binfo) = NULL_TREE;
BINFO_BASE_ACCESSES (binfo) = NULL;
BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
BINFO_SUBVTT_INDEX (binfo) = NULL_TREE;
BINFO_VPTR_FIELD (binfo) = NULL_TREE;
}
else
{
/* Otherwise, get rid of the whole binfo data. */
TYPE_BINFO (type) = NULL_TREE;
}
}
}
else
{
/* For non-aggregate types, clear out the language slot (which
overloads TYPE_BINFO). */
TYPE_LANG_SLOT_1 (type) = NULL_TREE;
}
TYPE_CONTEXT (type) = NULL_TREE;
TYPE_STUB_DECL (type) = NULL_TREE;
/* Remove type variants other than the main variant. This is both
wasteful and it may introduce infinite loops when the types are
read from disk and merged (since the variant will be the same
type as the main variant, traversing type variants will get into
an infinite loop). */
if (TYPE_MAIN_VARIANT (type))
TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (type)) = NULL_TREE;
TYPE_NEXT_VARIANT (type) = NULL_TREE;
}
/* Return true if DECL may need an assembler name to be set. */
static inline bool
need_assembler_name_p (tree decl)
{
/* Only FUNCTION_DECLs and VAR_DECLs are considered. */
if (TREE_CODE (decl) != FUNCTION_DECL
&& TREE_CODE (decl) != VAR_DECL)
return false;
/* If DECL already has its assembler name set, it does not need a
new one. */
if (!HAS_DECL_ASSEMBLER_NAME_P (decl)
|| DECL_ASSEMBLER_NAME_SET_P (decl))
return false;
/* For VAR_DECLs, only static, public and external symbols need an
assembler name. */
if (TREE_CODE (decl) == VAR_DECL
&& !TREE_STATIC (decl)
&& !TREE_PUBLIC (decl)
&& !DECL_EXTERNAL (decl))
return false;
/* Do not set assembler name on builtins. Allow RTL expansion to
decide whether to expand inline or via a regular call. */
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_BUILT_IN (decl)
&& DECL_BUILT_IN_CLASS (decl) != BUILT_IN_FRONTEND)
return false;
/* For FUNCTION_DECLs, only used functions and functions
represented in the callgraph need an assembler name. */
if (TREE_CODE (decl) == FUNCTION_DECL
&& cgraph_node_for_decl (decl) == NULL
&& !TREE_USED (decl))
return false;
return true;
}
/* Remove all the non-variable decls from BLOCK. LOCALS is the set of
variables in DECL_STRUCT_FUNCTION (FN)->local_decls. Every decl
in BLOCK that is not in LOCALS is removed. */
static void
free_lang_data_in_block (tree fn, tree block, struct pointer_set_t *locals)
{
tree *tp, t;
tp = &BLOCK_VARS (block);
while (*tp)
{
if (!pointer_set_contains (locals, *tp))
*tp = TREE_CHAIN (*tp);
else
tp = &TREE_CHAIN (*tp);
}
for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
free_lang_data_in_block (fn, t, locals);
}
/* Reset all language specific information still present in symbol
DECL. */
static void
free_lang_data_in_decl (tree decl)
{
gcc_assert (DECL_P (decl));
/* Give the FE a chance to remove its own data first. */
lang_hooks.free_lang_data (decl);
TREE_LANG_FLAG_0 (decl) = 0;
TREE_LANG_FLAG_1 (decl) = 0;
TREE_LANG_FLAG_2 (decl) = 0;
TREE_LANG_FLAG_3 (decl) = 0;
TREE_LANG_FLAG_4 (decl) = 0;
TREE_LANG_FLAG_5 (decl) = 0;
TREE_LANG_FLAG_6 (decl) = 0;
/* Identifiers need not have a type. */
if (DECL_NAME (decl))
TREE_TYPE (DECL_NAME (decl)) = NULL_TREE;
if (TREE_CODE (decl) == CONST_DECL)
DECL_CONTEXT (decl) = NULL_TREE;
/* Ignore any intervening types, because we are going to clear their
TYPE_CONTEXT fields. */
if (TREE_CODE (decl) != FIELD_DECL)
DECL_CONTEXT (decl) = decl_function_context (decl);
if (DECL_CONTEXT (decl)
&& TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
DECL_CONTEXT (decl) = NULL_TREE;
if (TREE_CODE (decl) == VAR_DECL)
{
tree context = DECL_CONTEXT (decl);
if (context)
{
enum tree_code code = TREE_CODE (context);
if (code == FUNCTION_DECL && DECL_ABSTRACT (context))
{
/* Do not clear the decl context here, that will promote
all vars to global ones. */
DECL_INITIAL (decl) = NULL_TREE;
}
if (TREE_STATIC (decl))
DECL_CONTEXT (decl) = NULL_TREE;
}
}
if (TREE_CODE (decl) == PARM_DECL
|| TREE_CODE (decl) == FIELD_DECL
|| TREE_CODE (decl) == RESULT_DECL)
{
tree unit_size = DECL_SIZE_UNIT (decl);
tree size = DECL_SIZE (decl);
if ((unit_size && TREE_CODE (unit_size) != INTEGER_CST)
|| (size && TREE_CODE (size) != INTEGER_CST))
{
DECL_SIZE_UNIT (decl) = NULL_TREE;
DECL_SIZE (decl) = NULL_TREE;
}
if (TREE_CODE (decl) == FIELD_DECL
&& DECL_FIELD_OFFSET (decl)
&& TREE_CODE (DECL_FIELD_OFFSET (decl)) != INTEGER_CST)
DECL_FIELD_OFFSET (decl) = NULL_TREE;
}
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
if (gimple_has_body_p (decl))
{
tree t;
struct pointer_set_t *locals;
/* If DECL has a gimple body, then the context for its
arguments must be DECL. Otherwise, it doesn't really
matter, as we will not be emitting any code for DECL. In
general, there may be other instances of DECL created by
the front end and since PARM_DECLs are generally shared,
their DECL_CONTEXT changes as the replicas of DECL are
created. The only time where DECL_CONTEXT is important
is for the FUNCTION_DECLs that have a gimple body (since
the PARM_DECL will be used in the function's body). */
for (t = DECL_ARGUMENTS (decl); t; t = TREE_CHAIN (t))
DECL_CONTEXT (t) = decl;
/* Collect all the symbols declared in DECL. */
locals = pointer_set_create ();
t = DECL_STRUCT_FUNCTION (decl)->local_decls;
for (; t; t = TREE_CHAIN (t))
{
pointer_set_insert (locals, TREE_VALUE (t));
/* All the local symbols should have DECL as their
context. */
DECL_CONTEXT (TREE_VALUE (t)) = decl;
}
/* Get rid of any decl not in local_decls. */
free_lang_data_in_block (decl, DECL_INITIAL (decl), locals);
pointer_set_destroy (locals);
}
/* DECL_SAVED_TREE holds the GENERIC representation for DECL.
At this point, it is not needed anymore. */
DECL_SAVED_TREE (decl) = NULL_TREE;
}
else if (TREE_CODE (decl) == VAR_DECL)
{
tree expr = DECL_DEBUG_EXPR (decl);
if (expr
&& TREE_CODE (expr) == VAR_DECL
&& !TREE_STATIC (expr) && !DECL_EXTERNAL (expr))
SET_DECL_DEBUG_EXPR (decl, NULL_TREE);
if (DECL_EXTERNAL (decl))
DECL_INITIAL (decl) = NULL_TREE;
}
else if (TREE_CODE (decl) == TYPE_DECL)
{
DECL_INITIAL (decl) = NULL_TREE;
/* DECL_CONTEXT is overloaded as DECL_FIELD_CONTEXT for
FIELD_DECLs, which should be preserved. Otherwise,
we shouldn't be concerned with source-level lexical
nesting beyond this point. */
DECL_CONTEXT (decl) = NULL_TREE;
}
}
/* Data used when collecting DECLs and TYPEs for language data removal. */
struct free_lang_data_d
{
/* Set of traversed objects. Used to avoid duplicate visits. */
struct pointer_set_t *pset;
/* Array of symbols to process with free_lang_data_in_decl. */
VEC(tree,heap) *decls;
/* Array of types to process with free_lang_data_in_type. */
VEC(tree,heap) *types;
};
/* Save all language fields needed to generate proper debug information
for DECL. This saves most fields cleared out by free_lang_data_in_decl. */
static void
save_debug_info_for_decl (tree t)
{
/*struct saved_debug_info_d *sdi;*/
gcc_assert (debug_info_level > DINFO_LEVEL_TERSE && t && DECL_P (t));
/* FIXME. Partial implementation for saving debug info removed. */
}
/* Save all language fields needed to generate proper debug information
for TYPE. This saves most fields cleared out by free_lang_data_in_type. */
static void
save_debug_info_for_type (tree t)
{
/*struct saved_debug_info_d *sdi;*/
gcc_assert (debug_info_level > DINFO_LEVEL_TERSE && t && TYPE_P (t));
/* FIXME. Partial implementation for saving debug info removed. */
}
/* Add type or decl T to one of the list of tree nodes that need their
language data removed. The lists are held inside FLD. */
static void
add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
{
if (DECL_P (t))
{
VEC_safe_push (tree, heap, fld->decls, t);
if (debug_info_level > DINFO_LEVEL_TERSE)
save_debug_info_for_decl (t);
}
else if (TYPE_P (t))
{
VEC_safe_push (tree, heap, fld->types, t);
if (debug_info_level > DINFO_LEVEL_TERSE)
save_debug_info_for_type (t);
}
else
gcc_unreachable ();
}
/* Operand callback helper for free_lang_data_in_node. *TP is the
subtree operand being considered. */
static tree
find_decls_types_r (tree *tp, int *ws ATTRIBUTE_UNUSED, void *data)
{
tree t = *tp;
struct free_lang_data_d *fld = (struct free_lang_data_d *) data;
if (DECL_P (t))
{
/* Note that walk_tree does not traverse every possible field in
decls, so we have to do our own traversals here. */
add_tree_to_fld_list (t, fld);
walk_tree (&DECL_NAME (t), find_decls_types_r, fld, fld->pset);
walk_tree (&DECL_CONTEXT (t), find_decls_types_r, fld, fld->pset);
walk_tree (&DECL_SIZE (t), find_decls_types_r, fld, fld->pset);
walk_tree (&DECL_SIZE_UNIT (t), find_decls_types_r, fld, fld->pset);
walk_tree (&DECL_INITIAL (t), find_decls_types_r, fld, fld->pset);
walk_tree (&DECL_ATTRIBUTES (t), find_decls_types_r, fld, fld->pset);
walk_tree (&DECL_ABSTRACT_ORIGIN (t), find_decls_types_r, fld, fld->pset);
if (TREE_CODE (t) == FUNCTION_DECL)
{
walk_tree (&DECL_ARGUMENTS (t), find_decls_types_r, fld, fld->pset);
walk_tree (&DECL_RESULT (t), find_decls_types_r, fld, fld->pset);
}
else if (TREE_CODE (t) == TYPE_DECL)
{
walk_tree (&DECL_ARGUMENT_FLD (t), find_decls_types_r, fld,
fld->pset);
walk_tree (&DECL_VINDEX (t), find_decls_types_r, fld, fld->pset);
}
else if (TREE_CODE (t) == FIELD_DECL)
{
walk_tree (&DECL_FIELD_OFFSET (t), find_decls_types_r, fld,
fld->pset);
walk_tree (&DECL_BIT_FIELD_TYPE (t), find_decls_types_r, fld,
fld->pset);
walk_tree (&DECL_QUALIFIER (t), find_decls_types_r, fld, fld->pset);
walk_tree (&DECL_FIELD_BIT_OFFSET (t), find_decls_types_r, fld,
fld->pset);
walk_tree (&DECL_FCONTEXT (t), find_decls_types_r, fld, fld->pset);
}
else if (TREE_CODE (t) == VAR_DECL)
{
walk_tree (&DECL_SECTION_NAME (t), find_decls_types_r, fld,
fld->pset);
walk_tree (&DECL_COMDAT_GROUP (t), find_decls_types_r, fld,
fld->pset);
}
}
else if (TYPE_P (t))
{
/* Note that walk_tree does not traverse every possible field in
types, so we have to do our own traversals here. */
add_tree_to_fld_list (t, fld);
walk_tree (&TYPE_CACHED_VALUES (t), find_decls_types_r, fld, fld->pset);
walk_tree (&TYPE_SIZE (t), find_decls_types_r, fld, fld->pset);
walk_tree (&TYPE_SIZE_UNIT (t), find_decls_types_r, fld, fld->pset);
walk_tree (&TYPE_ATTRIBUTES (t), find_decls_types_r, fld, fld->pset);
walk_tree (&TYPE_POINTER_TO (t), find_decls_types_r, fld, fld->pset);
walk_tree (&TYPE_REFERENCE_TO (t), find_decls_types_r, fld, fld->pset);
walk_tree (&TYPE_NAME (t), find_decls_types_r, fld, fld->pset);
walk_tree (&TYPE_MINVAL (t), find_decls_types_r, fld, fld->pset);
walk_tree (&TYPE_MAXVAL (t), find_decls_types_r, fld, fld->pset);
walk_tree (&TYPE_NEXT_VARIANT (t), find_decls_types_r, fld, fld->pset);
walk_tree (&TYPE_MAIN_VARIANT (t), find_decls_types_r, fld, fld->pset);
walk_tree (&TYPE_CONTEXT (t), find_decls_types_r, fld, fld->pset);
walk_tree (&TYPE_CANONICAL (t), find_decls_types_r, fld, fld->pset);
}
if (TREE_TYPE (t))
walk_tree (&TREE_TYPE (t), find_decls_types_r, fld, fld->pset);
/* Do not recurse into TREE_CHAIN to avoid blowing up the stack. */
for (tp = &TREE_CHAIN (t); *tp; tp = &TREE_CHAIN (*tp))
{
tree saved_chain = TREE_CHAIN (*tp);
TREE_CHAIN (*tp) = NULL_TREE;
walk_tree (tp, find_decls_types_r, fld, fld->pset);
TREE_CHAIN (*tp) = saved_chain;
}
return NULL_TREE;
}
/* Translate all the types in LIST with the corresponding runtime
types. */
static tree
get_eh_types_for_runtime (tree list)
{
tree head, prev;
if (list == NULL_TREE)
return NULL_TREE;
head = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list)));
prev = head;
list = TREE_CHAIN (list);
while (list)
{
tree n = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list)));
TREE_CHAIN (prev) = n;
prev = TREE_CHAIN (prev);
list = TREE_CHAIN (list);
}
return head;
}
/* Find decls and types referenced in EH region R and store them in
FLD->DECLS and FLD->TYPES. */
static void
find_decls_types_in_eh_region (eh_region r, struct free_lang_data_d *fld)
{
if (r == NULL)
return;
/* The types referenced in R must first be changed to the EH types
used at runtime. This removes references to FE types in the
region. */
if (r->type == ERT_CATCH)
{
tree list = r->u.eh_catch.type_list;
r->u.eh_catch.type_list = get_eh_types_for_runtime (list);
walk_tree (&r->u.eh_catch.type_list, find_decls_types_r, fld, fld->pset);
}
else if (r->type == ERT_ALLOWED_EXCEPTIONS)
{
tree list = r->u.allowed.type_list;
r->u.allowed.type_list = get_eh_types_for_runtime (list);
walk_tree (&r->u.allowed.type_list, find_decls_types_r, fld, fld->pset);
}
}
/* Find decls and types referenced in cgraph node N and store them in
FLD->DECLS and FLD->TYPES. Unlike pass_referenced_vars, this will
look for *every* kind of DECL and TYPE node reachable from N,
including those embedded inside types and decls (i.e,, TYPE_DECLs,
NAMESPACE_DECLs, etc). */
static void
find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
{
basic_block bb;
struct function *fn;
tree t;
walk_tree (&n->decl, find_decls_types_r, fld, fld->pset);
if (!gimple_has_body_p (n->decl))
return;
gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
fn = DECL_STRUCT_FUNCTION (n->decl);
/* Traverse locals. */
for (t = fn->local_decls; t; t = TREE_CHAIN (t))
{
tree *tp = &TREE_VALUE (t);
tree saved_chain = TREE_CHAIN (*tp);
TREE_CHAIN (*tp) = NULL_TREE;
walk_tree (tp, find_decls_types_r, fld, fld->pset);
TREE_CHAIN (*tp) = saved_chain;
}
/* Traverse EH regions in FN. */
if (fn->eh->region_array)
{
unsigned i;
eh_region r;
for (i = 0; VEC_iterate (eh_region, fn->eh->region_array, i, r); i++)
find_decls_types_in_eh_region (r, fld);
}
/* Traverse every statement in FN. */
FOR_EACH_BB_FN (bb, fn)
{
gimple_stmt_iterator si;
unsigned i;
for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
{
gimple phi = gsi_stmt (si);
for (i = 0; i < gimple_phi_num_args (phi); i++)
{
tree *arg_p = gimple_phi_arg_def_ptr (phi, i);
walk_tree (arg_p, find_decls_types_r, fld, fld->pset);
}
}
for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
{
gimple stmt = gsi_stmt (si);
for (i = 0; i < gimple_num_ops (stmt); i++)
{
tree *arg_p = gimple_op_ptr (stmt, i);
walk_tree (arg_p, find_decls_types_r, fld, fld->pset);
}
}
}
}
/* Find decls and types referenced in varpool node N and store them in
FLD->DECLS and FLD->TYPES. Unlike pass_referenced_vars, this will
look for *every* kind of DECL and TYPE node reachable from N,
including those embedded inside types and decls (i.e,, TYPE_DECLs,
NAMESPACE_DECLs, etc). */
static void
find_decls_types_in_var (struct varpool_node *v, struct free_lang_data_d *fld)
{
walk_tree (&v->decl, find_decls_types_r, fld, fld->pset);
}
/* Free language specific information for every operand and expression
in every node of the call graph. This process operates in three stages:
1- Every callgraph node and varpool node is traversed looking for
decls and types embedded in them. This is a more exhaustive
search than that done by find_referenced_vars, because it will
also collect individual fields, decls embedded in types, etc.
2- All the decls found are sent to free_lang_data_in_decl.
3- All the types found are sent to free_lang_data_in_type.
The ordering between decls and types is important because
free_lang_data_in_decl sets assembler names, which includes
mangling. So types cannot be freed up until assembler names have
been set up. */
static void
free_lang_data_in_cgraph (void)
{
struct cgraph_node *n;
struct varpool_node *v;
struct free_lang_data_d fld;
tree t;
unsigned i;
alias_pair *p;
/* Initialize sets and arrays to store referenced decls and types. */
fld.pset = pointer_set_create ();
fld.decls = VEC_alloc (tree, heap, 100);
fld.types = VEC_alloc (tree, heap, 100);
/* Find decls and types in the body of every function in the callgraph. */
for (n = cgraph_nodes; n; n = n->next)
find_decls_types_in_node (n, &fld);
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
walk_tree (&p->decl, find_decls_types_r, &fld, fld.pset);
/* Find decls and types in every varpool symbol. */
for (v = varpool_nodes_queue; v; v = v->next_needed)
find_decls_types_in_var (v, &fld);
/* Set the assembler name on every decl found. We need to do this
now because free_lang_data_in_decl will invalidate data needed
for mangling. This breaks mangling on interdependent decls. */
for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++)
if (need_assembler_name_p (t))
{
/* When setting DECL_ASSEMBLER_NAME, the C++ mangler may emit
diagnostics that use input_location to show locus
information. The problem here is that, at this point,
input_location is generally anchored to the end of the file
(since the parser is long gone), so we don't have a good
position to pin it to.
To alleviate this problem, this uses the location of T's
declaration. Examples of this are
testsuite/g++.dg/template/cond2.C and
testsuite/g++.dg/template/pr35240.C. */
location_t saved_location = input_location;
input_location = DECL_SOURCE_LOCATION (t);
decl_assembler_name (t);
input_location = saved_location;
}
/* Traverse every decl found freeing its language data. */
for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++)
free_lang_data_in_decl (t);
/* Traverse every type found freeing its language data. */
for (i = 0; VEC_iterate (tree, fld.types, i, t); i++)
free_lang_data_in_type (t);
pointer_set_destroy (fld.pset);
VEC_free (tree, heap, fld.decls);
VEC_free (tree, heap, fld.types);
}
/* Free resources that are used by FE but are not needed once they are done. */
static unsigned
free_lang_data (void)
{
/* Traverse the IL resetting language specific information for
operands, expressions, etc. */
free_lang_data_in_cgraph ();
/* Create gimple variants for common types. */
ptrdiff_type_node = integer_type_node;
fileptr_type_node = ptr_type_node;
if (TREE_CODE (boolean_type_node) != BOOLEAN_TYPE
|| (TYPE_MODE (boolean_type_node)
!= mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0))
|| TYPE_PRECISION (boolean_type_node) != 1
|| !TYPE_UNSIGNED (boolean_type_node))
{
boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
TYPE_MAX_VALUE (boolean_type_node) = build_int_cst (boolean_type_node, 1);
TYPE_PRECISION (boolean_type_node) = 1;
boolean_false_node = TYPE_MIN_VALUE (boolean_type_node);
boolean_true_node = TYPE_MAX_VALUE (boolean_type_node);
}
/* Reset some langhooks. */
lang_hooks.callgraph.analyze_expr = NULL;
lang_hooks.types_compatible_p = NULL;
lang_hooks.dwarf_name = lhd_dwarf_name;
lang_hooks.decl_printable_name = gimple_decl_printable_name;
lang_hooks.set_decl_assembler_name = lhd_set_decl_assembler_name;
lang_hooks.fold_obj_type_ref = gimple_fold_obj_type_ref;
/* Reset diagnostic machinery. */
diagnostic_starter (global_dc) = default_diagnostic_starter;
diagnostic_finalizer (global_dc) = default_diagnostic_finalizer;
diagnostic_format_decoder (global_dc) = default_tree_printer;
return 0;
}
/* Gate function for free_lang_data. */
static bool
gate_free_lang_data (void)
{
/* FIXME. Remove after save_debug_info is working. */
return !flag_gtoggle && debug_info_level <= DINFO_LEVEL_TERSE;
}
struct simple_ipa_opt_pass pass_ipa_free_lang_data =
{
{
SIMPLE_IPA_PASS,
NULL, /* name */
gate_free_lang_data, /* gate */
free_lang_data, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
TV_IPA_FREE_LANG_DATA, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
0 /* todo_flags_finish */
}
};
/* Return nonzero if IDENT is a valid name for attribute ATTR,
or zero if not.
@ -5292,6 +6082,9 @@ tree_int_cst_compare (const_tree t1, const_tree t2)
int
host_integerp (const_tree t, int pos)
{
if (t == NULL_TREE)
return 0;
return (TREE_CODE (t) == INTEGER_CST
&& ((TREE_INT_CST_HIGH (t) == 0
&& (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)

View File

@ -183,6 +183,22 @@ DEF_VEC_P(tree);
DEF_VEC_ALLOC_P(tree,gc);
DEF_VEC_ALLOC_P(tree,heap);
/* We have to be able to tell cgraph about the needed-ness of the target
of an alias. This requires that the decl have been defined. Aliases
that precede their definition have to be queued for later processing. */
typedef struct GTY(()) alias_pair
{
tree decl;
tree target;
} alias_pair;
/* Define gc'd vector type. */
DEF_VEC_O(alias_pair);
DEF_VEC_ALLOC_O(alias_pair,gc);
extern GTY(()) VEC(alias_pair,gc) * alias_pairs;
/* Classify which part of the compiler has defined a given builtin function.
Note that we assume below that this is no more than two bits. */
@ -1259,7 +1275,7 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
This is interesting in an inline function, since it might not need
to be compiled separately.
Nonzero in a RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE or ENUMERAL_TYPE
if the sdb debugging info for the type has been written.
if the debugging info for the type has been written.
In a BLOCK node, nonzero if reorder_blocks has already seen this block.
In an SSA_NAME node, nonzero if the SSA_NAME occurs in an abnormal
PHI node. */
@ -2035,6 +2051,8 @@ struct GTY(()) tree_block {
#define TYPE_NEXT_VARIANT(NODE) (TYPE_CHECK (NODE)->type.next_variant)
#define TYPE_MAIN_VARIANT(NODE) (TYPE_CHECK (NODE)->type.main_variant)
#define TYPE_CONTEXT(NODE) (TYPE_CHECK (NODE)->type.context)
#define TYPE_MAXVAL(NODE) (TYPE_CHECK (NODE)->type.maxval)
#define TYPE_MINVAL(NODE) (TYPE_CHECK (NODE)->type.minval)
/* Vector types need to check target flags to determine type. */
extern enum machine_mode vector_type_mode (const_tree);
@ -2439,9 +2457,9 @@ struct function;
/* For FIELD_DECLs, this is the RECORD_TYPE, UNION_TYPE, or
QUAL_UNION_TYPE node that the field is a member of. For VAR_DECL,
PARM_DECL, FUNCTION_DECL, LABEL_DECL, and CONST_DECL nodes, this
points to either the FUNCTION_DECL for the containing function,
the RECORD_TYPE or UNION_TYPE for the containing type, or
PARM_DECL, FUNCTION_DECL, LABEL_DECL, RESULT_DECL, and CONST_DECL
nodes, this points to either the FUNCTION_DECL for the containing
function, the RECORD_TYPE or UNION_TYPE for the containing type, or
NULL_TREE or a TRANSLATION_UNIT_DECL if the given decl has "file
scope". */
#define DECL_CONTEXT(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.context)
@ -4889,6 +4907,7 @@ extern hashval_t iterative_hash_exprs_commutative (const_tree,
const_tree, hashval_t);
extern hashval_t iterative_hash_host_wide_int (HOST_WIDE_INT, hashval_t);
extern hashval_t iterative_hash_hashval_t (hashval_t, hashval_t);
extern hashval_t iterative_hash_host_wide_int (HOST_WIDE_INT, hashval_t);
extern int compare_tree_int (const_tree, unsigned HOST_WIDE_INT);
extern int type_list_equal (const_tree, const_tree);
extern int chain_member (const_tree, const_tree);
@ -5047,6 +5066,7 @@ extern void process_pending_assemble_externals (void);
extern void finish_aliases_1 (void);
extern void finish_aliases_2 (void);
extern tree emutls_decl (tree);
extern void remove_unreachable_alias_pairs (void);
/* In stmt.c */
extern void expand_computed_goto (tree);

View File

@ -5369,20 +5369,7 @@ globalize_decl (tree decl)
targetm.asm_out.globalize_decl_name (asm_out_file, decl);
}
/* We have to be able to tell cgraph about the needed-ness of the target
of an alias. This requires that the decl have been defined. Aliases
that precede their definition have to be queued for later processing. */
typedef struct GTY(()) alias_pair {
tree decl;
tree target;
} alias_pair;
/* Define gc'd vector type. */
DEF_VEC_O(alias_pair);
DEF_VEC_ALLOC_O(alias_pair,gc);
static GTY(()) VEC(alias_pair,gc) *alias_pairs;
VEC(alias_pair,gc) *alias_pairs;
/* Given an assembly name, find the decl it is associated with. At the
same time, mark it needed for cgraph. */
@ -5526,6 +5513,39 @@ do_assemble_alias (tree decl, tree target)
#endif
}
/* Remove the alias pairing for functions that are no longer in the call
graph. */
void
remove_unreachable_alias_pairs (void)
{
unsigned i;
alias_pair *p;
if (alias_pairs == NULL)
return;
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); )
{
if (!DECL_EXTERNAL (p->decl))
{
struct cgraph_node *fnode = NULL;
struct varpool_node *vnode = NULL;
fnode = cgraph_node_for_asm (p->target);
vnode = (fnode == NULL) ? varpool_node_for_asm (p->target) : NULL;
if (fnode == NULL && vnode == NULL)
{
VEC_unordered_remove (alias_pair, alias_pairs, i);
continue;
}
}
i++;
}
}
/* First pass of completing pending aliases. Make sure that cgraph knows
which symbols will be required. */
@ -5547,6 +5567,11 @@ finish_aliases_1 (void)
p->decl, p->target);
}
else if (DECL_EXTERNAL (target_decl)
/* We use local aliases for C++ thunks to force the tailcall
to bind locally. Of course this is a hack - to keep it
working do the following (which is not strictly correct). */
&& (! TREE_CODE (target_decl) == FUNCTION_DECL
|| ! TREE_STATIC (target_decl))
&& ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
error ("%q+D aliased to external symbol %qE",
p->decl, p->target);