[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:
parent
e25ea117b5
commit
4537ec0c86
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
30
gcc/cgraph.c
30
gcc/cgraph.c
|
@ -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)))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
37
gcc/except.c
37
gcc/except.c
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
72
gcc/gimple.c
72
gcc/gimple.c
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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" } } */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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>();
|
||||
}
|
||||
|
|
|
@ -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" } } */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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" } } */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
793
gcc/tree.c
793
gcc/tree.c
|
@ -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)
|
||||
|
|
28
gcc/tree.h
28
gcc/tree.h
|
@ -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);
|
||||
|
|
53
gcc/varasm.c
53
gcc/varasm.c
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue