aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog84
-rw-r--r--gcc/Makefile.in3
-rw-r--r--gcc/ada/ChangeLog4
-rw-r--r--gcc/ada/gcc-interface/misc.c2
-rw-r--r--gcc/c-lang.c2
-rw-r--r--gcc/cgraph.c30
-rw-r--r--gcc/cgraph.h3
-rw-r--r--gcc/cgraphunit.c41
-rw-r--r--gcc/cp/ChangeLog29
-rw-r--r--gcc/cp/Make-lang.in2
-rw-r--r--gcc/cp/cp-lang.c2
-rw-r--r--gcc/cp/cp-objcp-common.h2
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl2.c56
-rw-r--r--gcc/cp/semantics.c4
-rw-r--r--gcc/cp/tree.c47
-rw-r--r--gcc/diagnostic.c9
-rw-r--r--gcc/diagnostic.h6
-rw-r--r--gcc/except.c37
-rw-r--r--gcc/fortran/ChangeLog4
-rw-r--r--gcc/fortran/f95-lang.c2
-rw-r--r--gcc/gimple.c72
-rw-r--r--gcc/gimple.h2
-rw-r--r--gcc/ipa.c5
-rw-r--r--gcc/java/ChangeLog4
-rw-r--r--gcc/java/lang.c2
-rw-r--r--gcc/langhooks-def.h2
-rw-r--r--gcc/langhooks.h5
-rw-r--r--gcc/objc/ChangeLog4
-rw-r--r--gcc/objc/objc-lang.c2
-rw-r--r--gcc/objcp/ChangeLog4
-rw-r--r--gcc/objcp/objcp-lang.c2
-rw-r--r--gcc/passes.c1
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/g++.dg/ipa/iinline-1.C2
-rw-r--r--gcc/testsuite/g++.dg/template/cond2.C4
-rw-r--r--gcc/testsuite/g++.dg/template/pr35240.C4
-rw-r--r--gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/unit-1.C2
-rw-r--r--gcc/testsuite/gcc.dg/gomp/combined-1.c2
-rw-r--r--gcc/timevar.def1
-rw-r--r--gcc/toplev.c4
-rw-r--r--gcc/tree-pass.h1
-rw-r--r--gcc/tree.c793
-rw-r--r--gcc/tree.h28
-rw-r--r--gcc/varasm.c53
46 files changed, 1319 insertions, 62 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c0e33a0..b0abc83 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 53c7ffed..526ec70 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -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
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 43c7542..9b92ce5 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -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.
diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 46e762f..f39a60e 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -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
diff --git a/gcc/c-lang.c b/gcc/c-lang.c
index 42004f5..7e0236d 100644
--- a/gcc/c-lang.c
+++ b/gcc/c-lang.c
@@ -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. */
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index f7a0f96..2f5bd2a 100644
--- a/gcc/cgraph.c
+++ b/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)))
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 6eadc27..67670ef 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -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);
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index eb7de10..1505b56 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -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
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0a351b2..bac7098 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index a3190f4..356565f 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -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 \
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 0278028..f818e5b 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -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. */
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 19fce29..818540c 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a76b2d2..23b41d3 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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,
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index da9c2b7..cc4317a 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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,27 +3289,60 @@ 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 void
-build_java_method_aliases (void)
+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;
+ return candidates;
#endif
for (node = cgraph_nodes; node ; node = node->next)
{
tree fndecl = node->decl;
- if (TREE_ASM_WRITTEN (fndecl)
- && DECL_CONTEXT (fndecl)
+ 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 (struct pointer_set_t *candidates)
+{
+ struct cgraph_node *node;
+
+#ifndef HAVE_GAS_HIDDEN
+ return;
+#endif
+
+ for (node = cgraph_nodes; node ; node = node->next)
+ {
+ tree fndecl = node->decl;
+
+ if (TREE_ASM_WRITTEN (fndecl)
+ && pointer_set_contains (candidates, fndecl))
+ {
/* Mangle the name in a predictable way; we need to reference
this from a java compiled object file. */
tree oid, nid, alias;
@@ -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 ();
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 1e5255e8..477140c 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index f09b036..808a18a 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index b8e025a..bca7478 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -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)
{
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index b9bff22..c2c08bc 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -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 */
diff --git a/gcc/except.c b/gcc/except.c
index ed489d9..c97928e 100644
--- a/gcc/except.c
+++ b/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
{
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 5afb061..aeae283 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -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.
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index 181f0fc..e061538 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -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
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 7db3410..9223aaa 100644
--- a/gcc/gimple.c
+++ b/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"
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 7a034a1..97d2c37 100644
--- a/gcc/gimple.h
+++ b/gcc/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);
diff --git a/gcc/ipa.c b/gcc/ipa.c
index fb3c749..9204caa 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -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;
}
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 1437c5a..569b5fe 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -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
diff --git a/gcc/java/lang.c b/gcc/java/lang.c
index 109ec51..d97b508 100644
--- a/gcc/java/lang.c
+++ b/gcc/java/lang.c
@@ -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
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index aebab55..63a0dcd 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -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, \
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index cf3bda0..8342004 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -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,
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index f1b5722..d499f0a 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -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
diff --git a/gcc/objc/objc-lang.c b/gcc/objc/objc-lang.c
index c8a3160..98f46d7 100644
--- a/gcc/objc/objc-lang.c
+++ b/gcc/objc/objc-lang.c
@@ -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. */
diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog
index a19627c..9acf08b 100644
--- a/gcc/objcp/ChangeLog
+++ b/gcc/objcp/ChangeLog
@@ -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>
diff --git a/gcc/objcp/objcp-lang.c b/gcc/objcp/objcp-lang.c
index 75cc6f2..1b54ba8 100644
--- a/gcc/objcp/objcp-lang.c
+++ b/gcc/objcp/objcp-lang.c
@@ -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. */
diff --git a/gcc/passes.c b/gcc/passes.c
index 7731da6..531dc60 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -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;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ba464ed..277bcc7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.dg/ipa/iinline-1.C b/gcc/testsuite/g++.dg/ipa/iinline-1.C
index 83490aa..1453c7e 100644
--- a/gcc/testsuite/g++.dg/ipa/iinline-1.C
+++ b/gcc/testsuite/g++.dg/ipa/iinline-1.C
@@ -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" } } */
diff --git a/gcc/testsuite/g++.dg/template/cond2.C b/gcc/testsuite/g++.dg/template/cond2.C
index abb6ebb..e6bd19d 100644
--- a/gcc/testsuite/g++.dg/template/cond2.C
+++ b/gcc/testsuite/g++.dg/template/cond2.C
@@ -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);
}
diff --git a/gcc/testsuite/g++.dg/template/pr35240.C b/gcc/testsuite/g++.dg/template/pr35240.C
index de82897..1972cf73 100644
--- a/gcc/testsuite/g++.dg/template/pr35240.C
+++ b/gcc/testsuite/g++.dg/template/pr35240.C
@@ -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>();
}
diff --git a/gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C b/gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C
index a0d4882..352e176 100644
--- a/gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C
+++ b/gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C
@@ -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" } } */
diff --git a/gcc/testsuite/g++.dg/warn/unit-1.C b/gcc/testsuite/g++.dg/warn/unit-1.C
index 9c09d3f..49bc231 100644
--- a/gcc/testsuite/g++.dg/warn/unit-1.C
+++ b/gcc/testsuite/g++.dg/warn/unit-1.C
@@ -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;
}
diff --git a/gcc/testsuite/gcc.dg/gomp/combined-1.c b/gcc/testsuite/gcc.dg/gomp/combined-1.c
index 7e23465..dfed647 100644
--- a/gcc/testsuite/gcc.dg/gomp/combined-1.c
+++ b/gcc/testsuite/gcc.dg/gomp/combined-1.c
@@ -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" } } */
diff --git a/gcc/timevar.def b/gcc/timevar.def
index 0e704cb..7e3d702 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -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. */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index b0e7039..1eaa893 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -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;
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index bc1ebda..4bb3364 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -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;
diff --git a/gcc/tree.c b/gcc/tree.c
index 66ac702..1db7d0a 100644
--- a/gcc/tree.c
+++ b/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)
diff --git a/gcc/tree.h b/gcc/tree.h
index 4d0cfd3..880f71d 100644
--- a/gcc/tree.h
+++ b/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);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 2a8fb11..d7f8611 100644
--- a/gcc/varasm.c
+++ b/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);