OSDN Git Service

2009-09-01 Diego Novillo <dnovillo@google.com>
authordnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 3 Sep 2009 04:07:12 +0000 (04:07 +0000)
committerdnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 3 Sep 2009 04:07:12 +0000 (04:07 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@151360 138bc75d-0d04-0410-961f-82ee72b054a4

46 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/ada/ChangeLog
gcc/ada/gcc-interface/misc.c
gcc/c-lang.c
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/cp-lang.c
gcc/cp/cp-objcp-common.h
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/diagnostic.c
gcc/diagnostic.h
gcc/except.c
gcc/fortran/ChangeLog
gcc/fortran/f95-lang.c
gcc/gimple.c
gcc/gimple.h
gcc/ipa.c
gcc/java/ChangeLog
gcc/java/lang.c
gcc/langhooks-def.h
gcc/langhooks.h
gcc/objc/ChangeLog
gcc/objc/objc-lang.c
gcc/objcp/ChangeLog
gcc/objcp/objcp-lang.c
gcc/passes.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ipa/iinline-1.C
gcc/testsuite/g++.dg/template/cond2.C
gcc/testsuite/g++.dg/template/pr35240.C
gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C
gcc/testsuite/g++.dg/warn/unit-1.C
gcc/testsuite/gcc.dg/gomp/combined-1.c
gcc/timevar.def
gcc/toplev.c
gcc/tree-pass.h
gcc/tree.c
gcc/tree.h
gcc/varasm.c

index c0e33a0..b0abc83 100644 (file)
@@ -1,3 +1,87 @@
+2009-09-03  Diego Novillo  <dnovillo@google.com>
+
+       * cgraph.c (cgraph_node_for_decl): New.
+       * cgraph.h (cgraph_node_for_decl): Declare.
+       * tree.c (host_integerp): Return 0 if T is NULL.
+
+2009-09-03  Diego Novillo  <dnovillo@google.com>
+
+       * tree.h (struct alias_pair): Move from varasm.c.
+       (alias_pairs): Likewise.
+       (TYPE_MAXVAL): Define.
+       (TYPE_MINVAL): Define.
+       (iterative_hash_host_wide_int): Declare.
+       (remove_unreachable_alias_pairs): Declare.
+       * tree-pass.h (pass_ipa_free_lang_data): Declare.
+       * diagnostic.c (default_diagnostic_starter): Make extern.
+       (default_diagnostic_finalizer): Make extern.
+       * diagnostic.h (default_diagnostic_starter): Declare.
+       (default_diagnostic_finalizer): Declare.
+       (default_tree_printer): Declare.
+       * toplev.c (default_tree_printer): Make extern.
+
+2009-09-03  Richard Guenther  <rguenther@suse.de>
+           Diego Novillo  <dnovillo@google.com>
+
+       * cgraph.c (cgraph_add_new_function): Remove gimplification.
+       * cgraphunit.c (cgraph_expand_function): Do not emit
+       associated thunks from here.
+       (cgraph_emit_thunks): New.
+       (cgraph_optimize): Call it.
+       Return if any IPA pass finds an error.
+       * varasm.c (finish_aliases_1): Ignore errorneous aliases used
+       by thunks.
+
+2009-09-03  Simon Baldwin  <simonb@google.com>
+           Rafael Espindola  <espindola@google.com>
+           Richard Guenther  <rguenther@suse.de>
+           Doug Kwan  <dougkwan@google.com>
+           Diego Novillo  <dnovillo@google.com>
+
+       * tree.c: Include tree-pass.h, langhooks-def.h,
+       diagnostic.h, cgraph.h, timevar.h, except.h and debug.h.
+       (free_lang_data_in_type): New.
+       (need_assembler_name_p): New.
+       (free_lang_data_in_block): New.
+       (free_lang_data_in_decl): New.
+       (struct free_lang_data_d): New.
+       (add_tree_to_fld_list): New.
+       (find_decls_types_r): New.
+       (get_eh_types_for_runtime): New.
+       (find_decls_types_in_eh_region): New.
+       (find_decls_types_in_node): New.
+       (find_decls_types_in_var): New.
+       (free_lang_data_in_cgraph): New.
+       (free_lang_data): New.
+       (gate_free_lang_data): New.
+       (pass_ipa_free_lang_data): New.
+
+2009-09-03  Diego Novillo  <dnovillo@google.com>
+
+       * timevar.def (TV_IPA_FREE_LANG_DATA): Define.
+       * langhooks.h (struct lang_hooks): Add field free_lang_data.
+       (lang_hooks): Remove const qualifier.
+       * ipa.c (cgraph_remove_unreachable_nodes): Call
+       remove_unreachable_alias_pairs.
+       * except.c (add_type_for_runtime): Check if TYPE has
+       already been converted.
+       (lookup_type_for_runtime): Likewise.
+       (check_handled): Handle converted types.
+       * varasm.c (remove_unreachable_alias_pairs): New.
+       * gimple.c: Include demangle.h.
+       (gimple_decl_printable_name): New.
+       (gimple_fold_obj_type_ref): New.
+       * gimple.h (gimple_decl_printable_name): Declare.
+       (gimple_fold_obj_type_ref): Declare.
+       * passes.c (init_optimization_passes): Add pass
+       pass_ipa_free_lang_data.
+       * langhooks-def.h (LANG_HOOKS_FREE_LANG_DATA): Define.
+       (LANG_HOOKS_INITIALIZER): Add LANG_HOOKS_FREE_LANG_DATA.
+
+2009-09-03  Diego Novillo  <dnovillo@google.com>
+
+       * c-lang.c (lang_hooks): Remove const qualifier.
+
 2009-09-02  Loren James Rittle  <ljrittle@acm.org>
 
        * doc/install.texi (*-*-freebsd*): Update target information.
index 53c7ffe..526ec70 100644 (file)
@@ -2164,7 +2164,8 @@ tree.o : tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
    all-tree.def $(FLAGS_H) $(FUNCTION_H) $(PARAMS_H) \
    $(TOPLEV_H) $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H) langhooks.h \
    $(REAL_H) gt-tree.h $(TREE_INLINE_H) tree-iterator.h $(BASIC_BLOCK_H) \
-   $(TREE_FLOW_H) $(OBSTACK_H) pointer-set.h fixed-value.h
+   $(TREE_FLOW_H) $(OBSTACK_H) pointer-set.h fixed-value.h tree-pass.h \
+   langhooks-def.h $(DIAGNOSTIC_H) $(CGRAPH_H) $(TIMEVAR_H) except.h debug.h
 tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TREE_H) langhooks.h $(TOPLEV_H) $(SPLAY_TREE_H) $(TREE_DUMP_H) \
    tree-iterator.h $(TREE_PASS_H) $(DIAGNOSTIC_H) $(REAL_H) fixed-value.h
index 43c7542..9b92ce5 100644 (file)
@@ -1,3 +1,7 @@
+2009-09-03  Diego Novillo  <dnovillo@google.com>
+
+       * gcc-interface/misc.c (lang_hooks): Remove const qualifier.
+
 2009-09-02  Richard Henderson  <rth@redhat.com>
 
        * tb-gcc.c (__gnat_backtrace): Mark all arguments unused.
index 46e762f..f39a60e 100644 (file)
@@ -131,7 +131,7 @@ static void gnat_get_subrange_bounds        (const_tree, tree *, tree *);
 #undef  LANG_HOOKS_BUILTIN_FUNCTION
 #define LANG_HOOKS_BUILTIN_FUNCTION        gnat_builtin_function
 
-const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
 
 /* How much we want of our DWARF extensions.  Some of our dwarf+ extensions
    are incompatible with regular GDB versions, so we must make sure to only
index 42004f5..7e0236d 100644 (file)
@@ -46,7 +46,7 @@ enum c_language_kind c_language = clk_c;
 #define LANG_HOOKS_INIT c_objc_common_init
 
 /* Each front end provides its own lang hook initializer.  */
-const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
 
 /* Final processing of file-scope data.  The Objective-C version of
    this function still does something.  */
index f7a0f96..2f5bd2a 100644 (file)
@@ -404,6 +404,33 @@ hash_node (const void *p)
   return (hashval_t) DECL_UID (n->decl);
 }
 
+
+/* Return the cgraph node associated with function DECL.  If none
+   exists, return NULL.  */
+
+struct cgraph_node *
+cgraph_node_for_decl (tree decl)
+{
+  struct cgraph_node *node;
+  void **slot;
+
+  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+
+  node = NULL;
+  if (cgraph_hash)
+    {
+      struct cgraph_node key;
+
+      key.decl = decl;
+      slot = htab_find_slot (cgraph_hash, &key, NO_INSERT);
+      if (slot && *slot)
+       node = (struct cgraph_node *) *slot;
+    }
+
+  return node;
+}
+
+
 /* Returns nonzero if P1 and P2 are equal.  */
 
 static int
@@ -1893,9 +1920,6 @@ cgraph_add_new_function (tree fndecl, bool lowered)
            push_cfun (DECL_STRUCT_FUNCTION (fndecl));
            current_function_decl = fndecl;
            gimple_register_cfg_hooks ();
-           /* C++ Thunks are emitted late via this function, gimplify them.  */
-           if (!gimple_body (fndecl))
-             gimplify_function_tree (fndecl);
            tree_lowering_passes (fndecl);
            bitmap_obstack_initialize (NULL);
            if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
index 6eadc27..67670ef 100644 (file)
@@ -391,7 +391,8 @@ struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
 
 struct cgraph_node * cgraph_get_node (tree);
 struct cgraph_node *cgraph_node (tree);
-struct cgraph_node *cgraph_node_for_asm (tree asmname);
+struct cgraph_node *cgraph_node_for_asm (tree);
+struct cgraph_node *cgraph_node_for_decl (tree);
 struct cgraph_edge *cgraph_edge (struct cgraph_node *, gimple);
 void cgraph_set_call_stmt (struct cgraph_edge *, gimple);
 void cgraph_set_call_stmt_including_clones (struct cgraph_node *, gimple, gimple);
index eb7de10..1505b56 100644 (file)
@@ -1108,9 +1108,6 @@ cgraph_expand_function (struct cgraph_node *node)
   gcc_assert (node->lowered);
 
   /* Generate RTL for the body of DECL.  */
-  if (lang_hooks.callgraph.emit_associated_thunks
-      && node->finalized_by_frontend)
-    lang_hooks.callgraph.emit_associated_thunks (decl);
   tree_rest_of_compilation (decl);
 
   /* Make sure that BE didn't give up on compiling.  */
@@ -1324,6 +1321,30 @@ ipa_passes (void)
   bitmap_obstack_release (NULL);
 }
 
+
+/* Emit thunks for every node in the cgraph.
+   FIXME: We really ought to emit thunks only for functions that are needed.  */
+
+static void
+cgraph_emit_thunks (void)
+{
+  struct cgraph_node *n;
+
+  for (n = cgraph_nodes; n; n = n->next)
+    {
+      /* Only emit thunks on functions defined in this TU.
+        Note that this may emit more thunks than strictly necessary.
+        During optimization some nodes may disappear.  It would be
+        nice to only emit thunks only for the functions that will be
+        emitted, but we cannot know that until the inliner and other
+        IPA passes have run (see the sequencing of the call to
+        cgraph_mark_functions_to_output in cgraph_optimize).  */
+      if (!DECL_EXTERNAL (n->decl))
+       lang_hooks.callgraph.emit_associated_thunks (n->decl);
+    }
+}
+
+
 /* Perform simple optimizations based on callgraph.  */
 
 static void
@@ -1336,6 +1357,14 @@ cgraph_optimize (void)
   verify_cgraph ();
 #endif
 
+  /* Emit thunks, if needed.  */
+  if (lang_hooks.callgraph.emit_associated_thunks)
+    {
+      cgraph_emit_thunks ();
+      if (errorcount || sorrycount)
+       return;
+    }
+
   /* Call functions declared with the "constructor" or "destructor"
      attribute.  */
   cgraph_build_cdtor_fns ();
@@ -1359,6 +1388,10 @@ cgraph_optimize (void)
   if (errorcount == 0 && sorrycount == 0)
     ipa_passes ();
 
+  /* Do nothing else if any IPA pass found errors.  */
+  if (errorcount || sorrycount)
+    return;
+
   /* This pass remove bodies of extern inline functions we never inlined.
      Do this later so other IPA passes see what is really going on.  */
   cgraph_remove_unreachable_nodes (false, dump_file);
@@ -1428,6 +1461,8 @@ cgraph_optimize (void)
     }
 #endif
 }
+
+
 /* Generate and emit a static constructor or destructor.  WHICH must
    be one of 'I' (for a constructor) or 'D' (for a destructor).  BODY
    is a STATEMENT_LIST containing GENERIC statements.  PRIORITY is the
index 0a351b2..bac7098 100644 (file)
@@ -1,3 +1,32 @@
+2009-09-03  Doug Kwan  <dougkwan@google.com>
+
+       * tree.c (cp_fix_function_decl_p): New.
+       (cp_free_lang_data): New.
+
+2009-09-03  Diego Novillo  <dnovillo@google.com>
+
+       * Make-lang.in (decl2.o): Add dependency on $(POINTER_SET_H).
+       * decl2.c: Include pointer-set.h.
+       (collect_candidates_for_java_method_aliases): New.
+       (cp_write_global_declarations): Call it.
+       Add local variable CANDIDATES.  If set, call
+       build_java_method_aliases.
+       (build_java_method_aliases): Add argument CANDIDATES.
+       Use it to determine if FNDECL should get a hidden alias.
+       * cp-objcp-common.h (LANG_HOOKS_FREE_LANG_DATA): Define.
+       * cp-tree.h (cp_free_lang_data): Declare.
+
+2009-09-03  Richard Guenther  <rguenther@suse.de>
+
+       * method.c (use_thunk): Use cgraph_finalize_function to hand
+       off thunks to the cgraph.
+       * semantics.c (emit_associated_thunks): Do not emit thunks
+       for really extern functions.
+
+2009-09-03  Diego Novillo  <dnovillo@google.com>
+
+       * cp-lang.c (lang_hooks): Remove const qualifier.
+
 2009-09-02  Jason Merrill  <jason@redhat.com>
 
        * semantics.c (describable_type): Don't pretend to be in a template.
index a3190f4..356565f 100644 (file)
@@ -257,7 +257,7 @@ cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h \
   debug.h gt-cp-decl.h $(TIMEVAR_H) $(TREE_FLOW_H) $(TARGET_H) $(PLUGIN_H)
 cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h $(EXPR_H) \
   output.h except.h toplev.h $(RTL_H) $(C_COMMON_H) gt-cp-decl2.h $(CGRAPH_H) \
-  $(C_PRAGMA_H) $(TREE_DUMP_H) intl.h $(TARGET_H) $(GIMPLE_H)
+  $(C_PRAGMA_H) $(TREE_DUMP_H) intl.h $(TARGET_H) $(GIMPLE_H) $(POINTER_SET_H)
 cp/cp-objcp-common.o : cp/cp-objcp-common.c $(CONFIG_H) $(SYSTEM_H) \
   coretypes.h $(TM_H) $(TREE_H) $(CXX_TREE_H) $(C_COMMON_H) toplev.h \
   langhooks.h $(LANGHOOKS_DEF_H) $(DIAGNOSTIC_H) debug.h \
index 0278028..f818e5b 100644 (file)
@@ -73,7 +73,7 @@ static enum classify_record cp_classify_record (tree type);
 #define LANG_HOOKS_INIT_TS cp_init_ts
 
 /* Each front end provides its own lang hook initializer.  */
-const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
 
 /* Lang hook routines common to C++ and ObjC++ appear in cp/cp-objcp-common.c;
    there should be very few routines below.  */
index 19fce29..818540c 100644 (file)
@@ -32,6 +32,8 @@ extern bool cp_function_decl_explicit_p (tree decl);
    specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c,
    respectively.  */
 
+#undef LANG_HOOKS_FREE_LANG_DATA
+#define LANG_HOOKS_FREE_LANG_DATA cp_free_lang_data
 #undef LANG_HOOKS_TREE_SIZE
 #define LANG_HOOKS_TREE_SIZE cp_tree_size
 #undef LANG_HOOKS_FINISH
index a76b2d2..23b41d3 100644 (file)
@@ -4891,6 +4891,7 @@ extern tree finish_decltype_type                (tree, bool);
 extern tree finish_trait_expr                  (enum cp_trait_kind, tree, tree);
 
 /* in tree.c */
+void cp_free_lang_data                                 (tree t);
 extern tree force_target_expr                  (tree, tree);
 extern tree build_target_expr_with_type                (tree, tree);
 extern void lang_check_failed                  (const char *, int,
index da9c2b7..cc4317a 100644 (file)
@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-dump.h"
 #include "intl.h"
 #include "gimple.h"
+#include "pointer-set.h"
 
 extern cpp_reader *parse_in;
 
@@ -3288,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 ();
 
index 1e5255e..477140c 100644 (file)
@@ -3186,7 +3186,9 @@ emit_associated_thunks (tree fn)
      is so that you can know statically the entire set of thunks that
      will ever be needed for a given virtual function, thereby
      enabling you to output all the thunks with the function itself.  */
-  if (DECL_VIRTUAL_P (fn))
+  if (DECL_VIRTUAL_P (fn)
+      /* Do not emit thunks for extern template instantiations.  */
+      && ! DECL_REALLY_EXTERN (fn))
     {
       tree thunk;
 
index f09b036..808a18a 100644 (file)
@@ -3030,6 +3030,53 @@ cast_valid_in_integral_constant_expression_p (tree type)
          || type == error_mark_node);
 }
 
+/* Return true if we need to fix linkage information of DECL.  */
+
+static bool
+cp_fix_function_decl_p (tree decl)
+{
+  /* Skip if DECL is not externally visible.  */
+  if (!TREE_PUBLIC (decl))
+    return false;
+
+  /* We need to fix DECL if it a appears to be exported but with no
+     function body.  Thunks do not have CFGs and we may need to
+     handle them specially later.   */
+  if (!gimple_has_body_p (decl)
+      && !DECL_THUNK_P (decl)
+      && !DECL_EXTERNAL (decl))
+    return true;
+
+  return false;
+}
+
+/* Clean the C++ specific parts of the tree T. */
+
+void
+cp_free_lang_data (tree t)
+{
+  if (TREE_CODE (t) == METHOD_TYPE
+      || TREE_CODE (t) == FUNCTION_TYPE)
+    {
+      /* Default args are not interesting anymore.  */
+      tree argtypes = TYPE_ARG_TYPES (t);
+      while (argtypes)
+        {
+         TREE_PURPOSE (argtypes) = 0;
+         argtypes = TREE_CHAIN (argtypes);
+       }
+    }
+  else if (TREE_CODE (t) == FUNCTION_DECL
+          && cp_fix_function_decl_p (t))
+    {
+      /* If T is used in this translation unit at all,  the definition
+        must exist somewhere else since we have decided to not emit it
+        in this TU.  So make it an external reference.  */
+      DECL_EXTERNAL (t) = 1;
+      TREE_STATIC (t) = 0;
+    }
+}
+
 \f
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 /* Complain that some language-specific thing hanging off a tree
index b8e025a..bca7478 100644 (file)
@@ -48,11 +48,6 @@ along with GCC; see the file COPYING3.  If not see
 /* Prototypes.  */
 static char *build_message_string (const char *, ...) ATTRIBUTE_PRINTF_1;
 
-static void default_diagnostic_starter (diagnostic_context *,
-                                       diagnostic_info *);
-static void default_diagnostic_finalizer (diagnostic_context *,
-                                         diagnostic_info *);
-
 static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
 
 static void diagnostic_action_after_output (diagnostic_context *,
@@ -266,7 +261,7 @@ diagnostic_report_current_module (diagnostic_context *context)
     }
 }
 
-static void
+void
 default_diagnostic_starter (diagnostic_context *context,
                            diagnostic_info *diagnostic)
 {
@@ -274,7 +269,7 @@ default_diagnostic_starter (diagnostic_context *context,
   pp_set_prefix (context->printer, diagnostic_build_prefix (diagnostic));
 }
 
-static void
+void
 default_diagnostic_finalizer (diagnostic_context *context,
                              diagnostic_info *diagnostic ATTRIBUTE_UNUSED)
 {
index b9bff22..c2c08bc 100644 (file)
@@ -213,6 +213,8 @@ extern bool emit_diagnostic (diagnostic_t, location_t, int,
                             const char *, ...) ATTRIBUTE_GCC_DIAG(4,5);
 #endif
 extern char *diagnostic_build_prefix (diagnostic_info *);
+void default_diagnostic_starter (diagnostic_context *, diagnostic_info *);
+void default_diagnostic_finalizer (diagnostic_context *, diagnostic_info *);
 
 /* Pure text formatting support functions.  */
 extern char *file_name_as_prefix (const char *);
@@ -239,4 +241,8 @@ extern void print_gimple_stmt (FILE *, gimple, int, int);
 extern void print_gimple_expr (FILE *, gimple, int, int);
 extern void dump_gimple_stmt (pretty_printer *, gimple, int, int);
 
+/* In toplev.c  */
+extern bool default_tree_printer (pretty_printer *, text_info *, const char *,
+                                 int, bool, bool, bool);
+
 #endif /* ! GCC_DIAGNOSTIC_H */
index ed489d9..c97928e 100644 (file)
@@ -1688,6 +1688,10 @@ add_type_for_runtime (tree type)
 {
   tree *slot;
 
+  /* If TYPE is NOP_EXPR, it means that it already is a runtime type.  */
+  if (TREE_CODE (type) == NOP_EXPR)
+    return;
+
   slot = (tree *) htab_find_slot_with_hash (type_to_runtime_map, type,
                                            TREE_HASH (type), INSERT);
   if (*slot == NULL)
@@ -1702,6 +1706,10 @@ lookup_type_for_runtime (tree type)
 {
   tree *slot;
 
+  /* If TYPE is NOP_EXPR, it means that it already is a runtime type.  */
+  if (TREE_CODE (type) == NOP_EXPR)
+    return type;
+
   slot = (tree *) htab_find_slot_with_hash (type_to_runtime_map, type,
                                            TREE_HASH (type), NO_INSERT);
 
@@ -2881,8 +2889,33 @@ check_handled (tree handled, tree type)
   if (! lang_eh_type_covers)
     {
       for (t = handled; t ; t = TREE_CHAIN (t))
-       if (TREE_VALUE (t) == type)
-         return 1;
+       {
+         tree t1 = TREE_VALUE (t);
+         tree t2 = type;
+
+         /* If the types have been converted to runtime types (i.e.,
+            when the IL is being read from disk in an LTO
+            compilation), then T1 and T2 will be pointers to the
+            runtime type of the form '(void *) &<runtime_type>' (See
+            cp/except.c:build_eh_type_type).  Strip the conversion
+            and the address.  */
+         if (CONVERT_EXPR_P (t1))
+           {
+             STRIP_NOPS (t1);
+             gcc_assert (TREE_CODE (t1) == ADDR_EXPR);
+             t1 = TREE_OPERAND (t1, 0);
+           }
+
+         if (CONVERT_EXPR_P (t2))
+           {
+             STRIP_NOPS (t2);
+             gcc_assert (TREE_CODE (t2) == ADDR_EXPR);
+             t2 = TREE_OPERAND (t2, 0);
+           }
+
+         if (t1 == t2)
+           return 1;
+       }
     }
   else
     {
index 5afb061..aeae283 100644 (file)
@@ -1,3 +1,7 @@
+2009-09-03  Diego Novillo  <dnovillo@google.com>
+
+       * f95-lang.c (lang_hooks): Remove const qualifier.
+
 2009-09-01  Richard Guenther  <rguenther@suse.de>
 
        * f95-lang.c (gfc_mark_addressable): Remove.
index 181f0fc..e061538 100644 (file)
@@ -154,7 +154,7 @@ static void gfc_init_ts (void);
 #define LANG_HOOKS_BUILTIN_FUNCTION          gfc_builtin_function
 #define LANG_HOOKS_GET_ARRAY_DESCR_INFO             gfc_get_array_descr_info
 
-const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
 
 #define NULL_BINDING_LEVEL (struct binding_level *) NULL
 
index 7db3410..9223aaa 100644 (file)
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-flow.h"
 #include "value-prof.h"
 #include "flags.h"
+#include "demangle.h"
 
 #define DEFGSCODE(SYM, NAME, STRUCT)   NAME,
 const char *const gimple_code_name[] = {
@@ -3427,4 +3428,75 @@ gimple_ior_addresses_taken (bitmap addresses_taken, gimple stmt)
                                        gimple_ior_addresses_taken_1);
 }
 
+
+/* Return a printable name for symbol DECL.  */
+
+const char *
+gimple_decl_printable_name (tree decl, int verbosity)
+{
+  gcc_assert (decl && DECL_NAME (decl));
+
+  if (DECL_ASSEMBLER_NAME_SET_P (decl))
+    {
+      const char *str, *mangled_str;
+      int dmgl_opts = DMGL_NO_OPTS;
+
+      if (verbosity >= 2)
+       {
+         dmgl_opts = DMGL_VERBOSE
+                     | DMGL_TYPES
+                     | DMGL_ANSI
+                     | DMGL_GNU_V3
+                     | DMGL_RET_POSTFIX;
+         if (TREE_CODE (decl) == FUNCTION_DECL)
+           dmgl_opts |= DMGL_PARAMS;
+       }
+
+      mangled_str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+      str = cplus_demangle_v3 (mangled_str, dmgl_opts);
+      return (str) ? str : mangled_str;
+    }
+
+  return IDENTIFIER_POINTER (DECL_NAME (decl));
+}
+
+
+/* Fold a OBJ_TYPE_REF expression to the address of a function.
+   KNOWN_TYPE carries the true type of OBJ_TYPE_REF_OBJECT(REF).  Adapted
+   from cp_fold_obj_type_ref, but it tolerates types with no binfo
+   data.  */
+
+tree
+gimple_fold_obj_type_ref (tree ref, tree known_type)
+{
+  HOST_WIDE_INT index;
+  HOST_WIDE_INT i;
+  tree v;
+  tree fndecl;
+
+  if (TYPE_BINFO (known_type) == NULL_TREE)
+    return NULL_TREE;
+
+  v = BINFO_VIRTUALS (TYPE_BINFO (known_type));
+  index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
+  i = 0;
+  while (i != index)
+    {
+      i += (TARGET_VTABLE_USES_DESCRIPTORS
+           ? TARGET_VTABLE_USES_DESCRIPTORS : 1);
+      v = TREE_CHAIN (v);
+    }
+
+  fndecl = TREE_VALUE (v);
+
+#ifdef ENABLE_CHECKING
+  gcc_assert (tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref),
+                                 DECL_VINDEX (fndecl)));
+#endif
+
+  cgraph_node (fndecl)->local.vtable_method = true;
+
+  return build_fold_addr_expr (fndecl);
+}
+
 #include "gt-gimple.h"
index 7a034a1..97d2c37 100644 (file)
@@ -836,6 +836,8 @@ bool gimple_assign_rhs_could_trap_p (gimple);
 void gimple_regimplify_operands (gimple, gimple_stmt_iterator *);
 bool empty_body_p (gimple_seq);
 unsigned get_gimple_rhs_num_ops (enum tree_code);
+const char *gimple_decl_printable_name (tree, int);
+tree gimple_fold_obj_type_ref (tree, tree);
 
 /* Returns true iff T is a valid GIMPLE statement.  */
 extern bool is_gimple_stmt (tree);
index fb3c749..9204caa 100644 (file)
--- 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;
 }
 
index 1437c5a..569b5fe 100644 (file)
@@ -1,3 +1,7 @@
+2009-09-03  Diego Novillo  <dnovillo@google.com>
+
+       * lang.c (lang_hooks): Remove const qualifier.
+
 2009-09-01  Jakub Jelinek  <jakub@redhat.com>
 
        * boehm.c (mark_reference_fields): Compute % in HOST_WIDE_INT
index 109ec51..d97b508 100644 (file)
@@ -159,7 +159,7 @@ struct GTY(()) language_function {
 #define LANG_HOOKS_ATTRIBUTE_TABLE java_attribute_table
 
 /* Each front end provides its own.  */
-const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
 
 /*
  * process java-specific compiler command-line options
index aebab55..63a0dcd 100644 (file)
@@ -99,6 +99,7 @@ extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *,
 #define LANG_HOOKS_PRINT_ERROR_FUNCTION lhd_print_error_function
 #define LANG_HOOKS_DECL_PRINTABLE_NAME lhd_decl_printable_name
 #define LANG_HOOKS_DWARF_NAME          lhd_dwarf_name
+#define LANG_HOOKS_FREE_LANG_DATA      lhd_do_nothing_t
 #define LANG_HOOKS_TREE_SIZE           lhd_tree_size
 #define LANG_HOOKS_TYPES_COMPATIBLE_P  lhd_types_compatible_p
 #define LANG_HOOKS_BUILTIN_FUNCTION    lhd_builtin_function
@@ -229,6 +230,7 @@ extern tree lhd_make_node (enum tree_code);
 #define LANG_HOOKS_INITIALIZER { \
   LANG_HOOKS_NAME, \
   LANG_HOOKS_IDENTIFIER_SIZE, \
+  LANG_HOOKS_FREE_LANG_DATA, \
   LANG_HOOKS_TREE_SIZE, \
   LANG_HOOKS_INIT_OPTIONS, \
   LANG_HOOKS_INITIALIZE_DIAGNOSTICS, \
index cf3bda0..8342004 100644 (file)
@@ -235,6 +235,9 @@ struct lang_hooks
      identifier nodes long enough for the language-specific slots.  */
   size_t identifier_size;
 
+  /* Remove any parts of the tree that are used only by the FE. */
+  void (*free_lang_data) (tree);
+
   /* Determines the size of any language-specific tcc_constant or
      tcc_exceptional nodes.  Since it is called from make_node, the
      only information available is the tree code.  Expected to die
@@ -416,7 +419,7 @@ struct lang_hooks
 };
 
 /* Each front end provides its own.  */
-extern const struct lang_hooks lang_hooks;
+extern struct lang_hooks lang_hooks;
 extern tree add_builtin_function (const char *name, tree type,
                                  int function_code, enum built_in_class cl,
                                  const char *library_name,
index f1b5722..d499f0a 100644 (file)
@@ -1,3 +1,7 @@
+2009-09-03  Diego Novillo  <dnovillo@google.com>
+
+       * objc-lang.c (lang_hooks): Remove const qualifier.
+
 2009-08-20  Richard Guenther  <rguenther@suse.de>
 
        * objc-act.c: Include c-lang.h
index c8a3160..98f46d7 100644 (file)
@@ -52,7 +52,7 @@ static void objc_init_ts (void);
 #define LANG_HOOKS_INIT_TS objc_init_ts
 
 /* Each front end provides its own lang hook initializer.  */
-const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
 
 /* Lang hook routines common to C and ObjC appear in c-objc-common.c;
    there should be very few (if any) routines below.  */
index a19627c..9acf08b 100644 (file)
@@ -1,3 +1,7 @@
+2009-09-03  Diego Novillo  <dnovillo@google.com>
+
+       * objcp-lang.c (lang_hooks): Remove const qualifier.
+
 2009-07-14  Taras Glek  <tglek@mozilla.com>
            Rafael Espindola  <espindola@google.com>
 
index 75cc6f2..1b54ba8 100644 (file)
@@ -52,7 +52,7 @@ static void objcxx_init_ts (void);
 #define LANG_HOOKS_INIT_TS objcxx_init_ts
 
 /* Each front end provides its own lang hook initializer.  */
-const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
 
 /* Lang hook routines common to C++ and ObjC++ appear in cp/cp-objcp-common.c;
    there should be very few (if any) routines below.  */
index 7731da6..531dc60 100644 (file)
@@ -535,6 +535,7 @@ init_optimization_passes (void)
       NEXT_PASS (pass_inline_parameters);
       NEXT_PASS (pass_rebuild_cgraph_edges);
     }
+  NEXT_PASS (pass_ipa_free_lang_data);
   NEXT_PASS (pass_early_local_passes);
     {
       struct opt_pass **p = &pass_early_local_passes.pass.sub;
index ba464ed..277bcc7 100644 (file)
@@ -1,3 +1,13 @@
+2009-09-03  Diego Novillo  <dnovillo@google.com>
+
+       * gcc.dg/gomp/combined-1.c: Adjust expected pattern.
+       * g++.dg/tree-prof/inline_mismatch_args.C: Likewise.
+       * g++.dg/warn/unit-1.C: Likewise.
+       * g++.dg/ipa/iinline-1.C: Likewise.
+       * g++.dg/template/cond2.C: Adjust expected line location for the
+       error.
+       * g++.dg/template/pr35240.C: Likewise.
+
 2009-09-02  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * gcc.dg/tree-ssa/inline-3.c: Add -fpie when pic.
index 83490aa..1453c7e 100644 (file)
@@ -44,5 +44,5 @@ int main (int argc, char *argv[])
   return 0;
 }
 
-/* { dg-final { scan-ipa-dump "String::funcOne\[^\\n\]*inline copy in int main"  "inline"  } } */
+/* { dg-final { scan-ipa-dump "String::funcOne\[^\\n\]*inline copy in main"  "inline"  } } */
 /* { dg-final { cleanup-ipa-dump "inline" } } */
index abb6ebb..e6bd19d 100644 (file)
@@ -3,8 +3,8 @@
 
 template<int X> class c;
 
-template<int X, int Y> int test(c<X ? : Y>&);
+template<int X, int Y> int test(c<X ? : Y>&); // { dg-error "omitted" }
 
 void test(c<2>*c2) {
-       test<0, 2>(*c2); // { dg-error "omitted" }
+       test<0, 2>(*c2);
 }
index de82897..1972cf7 100644 (file)
@@ -4,9 +4,9 @@
 
 template<int> struct A {};
 
-template<int N> A<sizeof(new int[N][N])> foo();
+template<int N> A<sizeof(new int[N][N])> foo();        // { dg-message "unimplemented" }
 
 void bar()
 {
-  foo<1>();    // { dg-message "unimplemented" }
+  foo<1>();
 }
index a0d4882..352e176 100644 (file)
@@ -31,6 +31,6 @@ int main(void)
  baz.Bar(&baz, gid);
  return 0;
 }
-/* { dg-final-use { scan-tree-dump "Inlining virtual void Super::Foo" "einline2"} } */                                                                                
+/* { dg-final-use { scan-tree-dump "Inlining .*Super::Foo" "einline2"} } */                                                                                
 /* { dg-final-use { scan-tree-dump-not "mismatched arguments" "einline2"} } */                                                                 
 /* { dg-final-use { cleanup-tree-dump "einline2" } } */
index 9c09d3f..49bc231 100644 (file)
@@ -4,7 +4,7 @@
 struct a { int mode; };
 int sys_msgctl (void)
 {
-  struct a setbuf;  /* { dg-warning "'setbuf\.a::mode' is used" "" { xfail *-*-* } } */
+  struct a setbuf;  /* { dg-warning "'setbuf.mode' is used" "" { xfail *-*-* } } */
   return setbuf.mode;
 }
 
index 7e23465..dfed647 100644 (file)
@@ -20,5 +20,5 @@ int foo (void)
       }
 }
 
-/* { dg-final { scan-tree-dump-times "__builtin_GOMP_parallel_loop_runtime_start" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_parallel_loop_runtime_start" 3 "optimized" } } */
 /* { dg-final { cleanup-tree-dump "optimized" } } */
index 0e704cb..7e3d702 100644 (file)
@@ -46,6 +46,7 @@ DEFTIMEVAR (TV_IPA_REFERENCE         , "ipa reference")
 DEFTIMEVAR (TV_IPA_PURE_CONST        , "ipa pure const")
 DEFTIMEVAR (TV_IPA_TYPE_ESCAPE       , "ipa type escape")
 DEFTIMEVAR (TV_IPA_PTA               , "ipa points-to")
+DEFTIMEVAR (TV_IPA_FREE_LANG_DATA    , "ipa free lang data")
 /* Time spent by constructing CFG.  */
 DEFTIMEVAR (TV_CFG                   , "cfg construction")
 /* Time spent by cleaning up CFG.  */
index b0e7039..1eaa893 100644 (file)
@@ -1576,8 +1576,8 @@ default_pch_valid_p (const void *data_p, size_t len)
 }
 
 /* Default tree printer.   Handles declarations only.  */
-static bool
-default_tree_printer (pretty_printer * pp, text_info *text, const char *spec,
+bool
+default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
                      int precision, bool wide, bool set_locus, bool hash)
 {
   tree t;
index bc1ebda..4bb3364 100644 (file)
@@ -409,6 +409,7 @@ extern struct gimple_opt_pass pass_warn_unused_result;
 
 /* IPA Passes */
 extern struct ipa_opt_pass_d pass_ipa_inline;
+extern struct simple_ipa_opt_pass pass_ipa_free_lang_data;
 extern struct ipa_opt_pass_d pass_ipa_cp;
 extern struct ipa_opt_pass_d pass_ipa_reference;
 extern struct ipa_opt_pass_d pass_ipa_pure_const;
index 66ac702..1db7d0a 100644 (file)
@@ -52,6 +52,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "params.h"
 #include "pointer-set.h"
 #include "fixed-value.h"
+#include "tree-pass.h"
+#include "langhooks-def.h"
+#include "diagnostic.h"
+#include "cgraph.h"
+#include "timevar.h"
+#include "except.h"
+#include "debug.h"
 
 /* Tree code classes.  */
 
@@ -4124,6 +4131,789 @@ build_type_attribute_variant (tree ttype, tree attribute)
                                            TYPE_QUALS (ttype));
 }
 
+/* Reset all language specific information still present in TYPE.  */
+
+static void
+free_lang_data_in_type (tree type)
+{
+  gcc_assert (TYPE_P (type));
+
+  /* Fill in the alias-set.  We need to at least track zeroness here
+     for correctness.  */
+  if (lang_hooks.get_alias_set (type) == 0)
+    TYPE_ALIAS_SET (type) = 0;
+
+  /* Give the FE a chance to remove its own data first.  */
+  lang_hooks.free_lang_data (type);
+
+  TREE_LANG_FLAG_0 (type) = 0;
+  TREE_LANG_FLAG_1 (type) = 0;
+  TREE_LANG_FLAG_2 (type) = 0;
+  TREE_LANG_FLAG_3 (type) = 0;
+  TREE_LANG_FLAG_4 (type) = 0;
+  TREE_LANG_FLAG_5 (type) = 0;
+  TREE_LANG_FLAG_6 (type) = 0;
+
+  if (TREE_CODE (type) == FUNCTION_TYPE)
+    {
+      /* Remove the const and volatile qualifiers from arguments.  The
+        C++ front end removes them, but the C front end does not,
+        leading to false ODR violation errors when merging two
+        instances of the same function signature compiled by
+        different front ends.  */
+      tree p;
+
+      for (p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
+       {
+         tree arg_type = TREE_VALUE (p);
+
+         if (TYPE_READONLY (arg_type) || TYPE_VOLATILE (arg_type))
+           {
+             int quals = TYPE_QUALS (arg_type)
+                         & ~TYPE_QUAL_CONST
+                         & ~TYPE_QUAL_VOLATILE;
+             TREE_VALUE (p) = build_qualified_type (arg_type, quals);
+             free_lang_data_in_type (TREE_VALUE (p));
+           }
+       }
+    }
+             
+  /* Remove members that are not actually FIELD_DECLs from the field
+     list of an aggregate.  These occur in C++.  */
+  if (TREE_CODE (type) == RECORD_TYPE
+      || TREE_CODE (type) == UNION_TYPE
+      || TREE_CODE (type) == QUAL_UNION_TYPE)
+    {
+      tree prev, member;
+
+      /* Note that TYPE_FIELDS can be shared across distinct
+        TREE_TYPEs.  Therefore, if the first field of TYPE_FIELDS is
+        to be removed, we cannot set its TREE_CHAIN to NULL.
+        Otherwise, we would not be able to find all the other fields
+        in the other instances of this TREE_TYPE.
+        
+        This was causing an ICE in testsuite/g++.dg/lto/20080915.C.  */
+      prev = NULL_TREE;
+      member = TYPE_FIELDS (type);
+      while (member)
+       {
+         if (TREE_CODE (member) == FIELD_DECL)
+           {
+             if (prev)
+               TREE_CHAIN (prev) = member;
+             else
+               TYPE_FIELDS (type) = member;
+             prev = member;
+           }
+
+         member = TREE_CHAIN (member);
+       }
+
+      if (prev)
+       TREE_CHAIN (prev) = NULL_TREE;
+      else
+       TYPE_FIELDS (type) = NULL_TREE;
+
+      TYPE_METHODS (type) = NULL_TREE;
+      if (TYPE_BINFO (type))
+       {
+         tree binfo = TYPE_BINFO (type);
+
+         if (BINFO_VIRTUALS (binfo))
+           {
+             /* If the virtual function table for BINFO contains
+                entries, these may be useful for folding OBJ_TYPE_REF
+                expressions (see gimple_fold_obj_type_ref).  In that
+                case, we only clear the unused fields in the BINFO
+                structure.  */
+             BINFO_OFFSET (binfo) = NULL_TREE;
+             BINFO_VTABLE (binfo) = NULL_TREE;
+             BINFO_VPTR_FIELD (binfo) = NULL_TREE;
+             BINFO_BASE_ACCESSES (binfo) = NULL;
+             BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
+             BINFO_SUBVTT_INDEX (binfo) = NULL_TREE;
+             BINFO_VPTR_FIELD (binfo) = NULL_TREE;
+           }
+         else
+           {
+             /* Otherwise, get rid of the whole binfo data.  */
+             TYPE_BINFO (type) = NULL_TREE;
+           }
+       }
+    }
+  else
+    {
+      /* For non-aggregate types, clear out the language slot (which
+        overloads TYPE_BINFO).  */
+      TYPE_LANG_SLOT_1 (type) = NULL_TREE;
+    }
+
+  TYPE_CONTEXT (type) = NULL_TREE;
+  TYPE_STUB_DECL (type) = NULL_TREE;
+
+  /* Remove type variants other than the main variant.  This is both
+     wasteful and it may introduce infinite loops when the types are
+     read from disk and merged (since the variant will be the same
+     type as the main variant, traversing type variants will get into
+     an infinite loop).  */
+  if (TYPE_MAIN_VARIANT (type))
+    TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (type)) = NULL_TREE;
+
+  TYPE_NEXT_VARIANT (type) = NULL_TREE;
+}
+
+
+/* Return true if DECL may need an assembler name to be set.  */
+
+static inline bool
+need_assembler_name_p (tree decl)
+{
+  /* Only FUNCTION_DECLs and VAR_DECLs are considered.  */
+  if (TREE_CODE (decl) != FUNCTION_DECL
+      && TREE_CODE (decl) != VAR_DECL)
+    return false;
+
+  /* If DECL already has its assembler name set, it does not need a
+     new one.  */
+  if (!HAS_DECL_ASSEMBLER_NAME_P (decl)
+      || DECL_ASSEMBLER_NAME_SET_P (decl))
+    return false;
+
+  /* For VAR_DECLs, only static, public and external symbols need an
+     assembler name.  */
+  if (TREE_CODE (decl) == VAR_DECL
+      && !TREE_STATIC (decl)
+      && !TREE_PUBLIC (decl)
+      && !DECL_EXTERNAL (decl))
+    return false;
+
+  /* Do not set assembler name on builtins.  Allow RTL expansion to
+     decide whether to expand inline or via a regular call.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && DECL_BUILT_IN (decl)
+      && DECL_BUILT_IN_CLASS (decl) != BUILT_IN_FRONTEND)
+    return false;
+
+  /* For FUNCTION_DECLs, only used functions and functions
+     represented in the callgraph need an assembler name.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && cgraph_node_for_decl (decl) == NULL
+      && !TREE_USED (decl))
+    return false;
+
+  return true;
+}
+
+
+/* Remove all the non-variable decls from BLOCK.  LOCALS is the set of
+   variables in DECL_STRUCT_FUNCTION (FN)->local_decls.  Every decl
+   in BLOCK that is not in LOCALS is removed.  */
+
+static void
+free_lang_data_in_block (tree fn, tree block, struct pointer_set_t *locals)
+{
+  tree *tp, t;
+
+  tp = &BLOCK_VARS (block);
+  while (*tp)
+    {
+      if (!pointer_set_contains (locals, *tp))
+       *tp = TREE_CHAIN (*tp);
+      else
+       tp = &TREE_CHAIN (*tp);
+    }
+
+  for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
+    free_lang_data_in_block (fn, t, locals);
+}
+
+
+/* Reset all language specific information still present in symbol
+   DECL.  */
+
+static void
+free_lang_data_in_decl (tree decl)
+{
+  gcc_assert (DECL_P (decl));
+
+  /* Give the FE a chance to remove its own data first.  */
+  lang_hooks.free_lang_data (decl);
+
+  TREE_LANG_FLAG_0 (decl) = 0;
+  TREE_LANG_FLAG_1 (decl) = 0;
+  TREE_LANG_FLAG_2 (decl) = 0;
+  TREE_LANG_FLAG_3 (decl) = 0;
+  TREE_LANG_FLAG_4 (decl) = 0;
+  TREE_LANG_FLAG_5 (decl) = 0;
+  TREE_LANG_FLAG_6 (decl) = 0;
+
+  /* Identifiers need not have a type.  */
+  if (DECL_NAME (decl))
+    TREE_TYPE (DECL_NAME (decl)) = NULL_TREE;
+
+  if (TREE_CODE (decl) == CONST_DECL)
+    DECL_CONTEXT (decl) = NULL_TREE;
+
+  /* Ignore any intervening types, because we are going to clear their
+     TYPE_CONTEXT fields.  */
+  if (TREE_CODE (decl) != FIELD_DECL)
+    DECL_CONTEXT (decl) = decl_function_context (decl);
+
+  if (DECL_CONTEXT (decl)
+      && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
+    DECL_CONTEXT (decl) = NULL_TREE;
+
+ if (TREE_CODE (decl) == VAR_DECL)
+   {
+     tree context = DECL_CONTEXT (decl);
+
+     if (context)
+       {
+        enum tree_code code = TREE_CODE (context);
+        if (code == FUNCTION_DECL && DECL_ABSTRACT (context))
+          {
+            /* Do not clear the decl context here, that will promote
+               all vars to global ones.  */
+            DECL_INITIAL (decl) = NULL_TREE;
+          }
+
+        if (TREE_STATIC (decl))
+          DECL_CONTEXT (decl) = NULL_TREE;
+       }
+   }
+
+  if (TREE_CODE (decl) == PARM_DECL
+      || TREE_CODE (decl) == FIELD_DECL
+      || TREE_CODE (decl) == RESULT_DECL)
+    {
+      tree unit_size = DECL_SIZE_UNIT (decl);
+      tree size = DECL_SIZE (decl);
+      if ((unit_size && TREE_CODE (unit_size) != INTEGER_CST)
+         || (size && TREE_CODE (size) != INTEGER_CST))
+       {
+         DECL_SIZE_UNIT (decl) = NULL_TREE;
+         DECL_SIZE (decl) = NULL_TREE;
+       }
+
+      if (TREE_CODE (decl) == FIELD_DECL
+         && DECL_FIELD_OFFSET (decl)
+         && TREE_CODE (DECL_FIELD_OFFSET (decl)) != INTEGER_CST)
+       DECL_FIELD_OFFSET (decl) = NULL_TREE;
+    }
+  else if (TREE_CODE (decl) == FUNCTION_DECL)
+    {
+      if (gimple_has_body_p (decl))
+       {
+         tree t;
+         struct pointer_set_t *locals;
+
+         /* If DECL has a gimple body, then the context for its
+            arguments must be DECL.  Otherwise, it doesn't really
+            matter, as we will not be emitting any code for DECL.  In
+            general, there may be other instances of DECL created by
+            the front end and since PARM_DECLs are generally shared,
+            their DECL_CONTEXT changes as the replicas of DECL are
+            created.  The only time where DECL_CONTEXT is important
+            is for the FUNCTION_DECLs that have a gimple body (since
+            the PARM_DECL will be used in the function's body).  */
+         for (t = DECL_ARGUMENTS (decl); t; t = TREE_CHAIN (t))
+           DECL_CONTEXT (t) = decl;
+
+         /* Collect all the symbols declared in DECL.  */
+         locals = pointer_set_create ();
+         t = DECL_STRUCT_FUNCTION (decl)->local_decls;
+         for (; t; t = TREE_CHAIN (t))
+           {
+             pointer_set_insert (locals, TREE_VALUE (t));
+
+             /* All the local symbols should have DECL as their
+                context.  */
+             DECL_CONTEXT (TREE_VALUE (t)) = decl;
+           }
+
+         /* Get rid of any decl not in local_decls.  */
+         free_lang_data_in_block (decl, DECL_INITIAL (decl), locals);
+
+         pointer_set_destroy (locals);
+       }
+
+      /* DECL_SAVED_TREE holds the GENERIC representation for DECL.
+        At this point, it is not needed anymore.  */
+      DECL_SAVED_TREE (decl) = NULL_TREE;
+    }
+  else if (TREE_CODE (decl) == VAR_DECL)
+    {
+      tree expr = DECL_DEBUG_EXPR (decl);
+      if (expr
+         && TREE_CODE (expr) == VAR_DECL
+         && !TREE_STATIC (expr) && !DECL_EXTERNAL (expr))
+       SET_DECL_DEBUG_EXPR (decl, NULL_TREE);
+
+      if (DECL_EXTERNAL (decl))
+       DECL_INITIAL (decl) = NULL_TREE;
+    }
+  else if (TREE_CODE (decl) == TYPE_DECL)
+    {
+      DECL_INITIAL (decl) = NULL_TREE;
+  
+      /* DECL_CONTEXT is overloaded as DECL_FIELD_CONTEXT for
+        FIELD_DECLs, which should be preserved.  Otherwise,
+        we shouldn't be concerned with source-level lexical
+        nesting beyond this point. */
+      DECL_CONTEXT (decl) = NULL_TREE;
+    }
+}
+
+
+/* Data used when collecting DECLs and TYPEs for language data removal.  */
+
+struct free_lang_data_d
+{
+  /* Set of traversed objects.  Used to avoid duplicate visits.  */
+  struct pointer_set_t *pset;
+
+  /* Array of symbols to process with free_lang_data_in_decl.  */
+  VEC(tree,heap) *decls;
+
+  /* Array of types to process with free_lang_data_in_type.  */
+  VEC(tree,heap) *types;
+};
+
+
+/* Save all language fields needed to generate proper debug information
+   for DECL.  This saves most fields cleared out by free_lang_data_in_decl.  */
+
+static void
+save_debug_info_for_decl (tree t)
+{
+  /*struct saved_debug_info_d *sdi;*/
+
+  gcc_assert (debug_info_level > DINFO_LEVEL_TERSE && t && DECL_P (t));
+
+  /* FIXME.  Partial implementation for saving debug info removed.  */
+}
+
+
+/* Save all language fields needed to generate proper debug information
+   for TYPE.  This saves most fields cleared out by free_lang_data_in_type.  */
+
+static void
+save_debug_info_for_type (tree t)
+{
+  /*struct saved_debug_info_d *sdi;*/
+
+  gcc_assert (debug_info_level > DINFO_LEVEL_TERSE && t && TYPE_P (t));
+
+  /* FIXME.  Partial implementation for saving debug info removed.  */
+}
+
+
+/* Add type or decl T to one of the list of tree nodes that need their
+   language data removed.  The lists are held inside FLD.  */
+
+static void
+add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
+{
+  if (DECL_P (t))
+    {
+      VEC_safe_push (tree, heap, fld->decls, t);
+      if (debug_info_level > DINFO_LEVEL_TERSE)
+       save_debug_info_for_decl (t);
+    }
+  else if (TYPE_P (t))
+    {
+      VEC_safe_push (tree, heap, fld->types, t);
+      if (debug_info_level > DINFO_LEVEL_TERSE)
+       save_debug_info_for_type (t);
+    }
+  else
+    gcc_unreachable ();
+}
+
+
+/* Operand callback helper for free_lang_data_in_node.  *TP is the
+   subtree operand being considered.  */
+
+static tree
+find_decls_types_r (tree *tp, int *ws ATTRIBUTE_UNUSED, void *data)
+{
+  tree t = *tp;
+  struct free_lang_data_d *fld = (struct free_lang_data_d *) data;
+
+  if (DECL_P (t))
+    {
+      /* Note that walk_tree does not traverse every possible field in
+        decls, so we have to do our own traversals here.  */
+      add_tree_to_fld_list (t, fld);
+
+      walk_tree (&DECL_NAME (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&DECL_CONTEXT (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&DECL_SIZE (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&DECL_SIZE_UNIT (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&DECL_INITIAL (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&DECL_ATTRIBUTES (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&DECL_ABSTRACT_ORIGIN (t), find_decls_types_r, fld, fld->pset);
+
+      if (TREE_CODE (t) == FUNCTION_DECL)
+       {
+         walk_tree (&DECL_ARGUMENTS (t), find_decls_types_r, fld, fld->pset);
+         walk_tree (&DECL_RESULT (t), find_decls_types_r, fld, fld->pset);
+       }
+      else if (TREE_CODE (t) == TYPE_DECL)
+       {
+         walk_tree (&DECL_ARGUMENT_FLD (t), find_decls_types_r, fld,
+                    fld->pset);
+         walk_tree (&DECL_VINDEX (t), find_decls_types_r, fld, fld->pset);
+       }
+      else if (TREE_CODE (t) == FIELD_DECL)
+       {
+         walk_tree (&DECL_FIELD_OFFSET (t), find_decls_types_r, fld,
+                    fld->pset);
+         walk_tree (&DECL_BIT_FIELD_TYPE (t), find_decls_types_r, fld,
+                    fld->pset);
+         walk_tree (&DECL_QUALIFIER (t), find_decls_types_r, fld, fld->pset);
+         walk_tree (&DECL_FIELD_BIT_OFFSET (t), find_decls_types_r, fld,
+                    fld->pset);
+         walk_tree (&DECL_FCONTEXT (t), find_decls_types_r, fld, fld->pset);
+       }
+      else if (TREE_CODE (t) == VAR_DECL)
+       {
+         walk_tree (&DECL_SECTION_NAME (t), find_decls_types_r, fld,
+                    fld->pset);
+         walk_tree (&DECL_COMDAT_GROUP (t), find_decls_types_r, fld,
+                    fld->pset);
+       }
+    }
+  else if (TYPE_P (t))
+    {
+      /* Note that walk_tree does not traverse every possible field in
+        types, so we have to do our own traversals here.  */
+      add_tree_to_fld_list (t, fld);
+
+      walk_tree (&TYPE_CACHED_VALUES (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_SIZE (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_SIZE_UNIT (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_ATTRIBUTES (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_POINTER_TO (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_REFERENCE_TO (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_NAME (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_MINVAL (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_MAXVAL (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_NEXT_VARIANT (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_MAIN_VARIANT (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_CONTEXT (t), find_decls_types_r, fld, fld->pset);
+      walk_tree (&TYPE_CANONICAL (t), find_decls_types_r, fld, fld->pset);
+    }
+
+  if (TREE_TYPE (t))
+    walk_tree (&TREE_TYPE (t), find_decls_types_r, fld, fld->pset);
+
+  /* Do not recurse into TREE_CHAIN to avoid blowing up the stack.  */
+  for (tp = &TREE_CHAIN (t); *tp; tp = &TREE_CHAIN (*tp))
+    {
+      tree saved_chain = TREE_CHAIN (*tp);
+      TREE_CHAIN (*tp) = NULL_TREE;
+      walk_tree (tp, find_decls_types_r, fld, fld->pset);
+      TREE_CHAIN (*tp) = saved_chain;
+    }
+
+  return NULL_TREE;
+}
+
+
+/* Translate all the types in LIST with the corresponding runtime
+   types.  */
+
+static tree
+get_eh_types_for_runtime (tree list)
+{
+  tree head, prev;
+
+  if (list == NULL_TREE)
+    return NULL_TREE;
+
+  head = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list)));
+  prev = head;
+  list = TREE_CHAIN (list);
+  while (list)
+    {
+      tree n = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list)));
+      TREE_CHAIN (prev) = n;
+      prev = TREE_CHAIN (prev);
+      list = TREE_CHAIN (list);
+    }
+
+  return head;
+}
+
+
+/* Find decls and types referenced in EH region R and store them in
+   FLD->DECLS and FLD->TYPES.  */
+
+static void
+find_decls_types_in_eh_region (eh_region r, struct free_lang_data_d *fld)
+{
+  if (r == NULL)
+    return;
+
+  /* The types referenced in R must first be changed to the EH types
+     used at runtime.  This removes references to FE types in the
+     region.  */
+  if (r->type == ERT_CATCH)
+    {
+      tree list = r->u.eh_catch.type_list;
+      r->u.eh_catch.type_list = get_eh_types_for_runtime (list);
+      walk_tree (&r->u.eh_catch.type_list, find_decls_types_r, fld, fld->pset);
+    }
+  else if (r->type == ERT_ALLOWED_EXCEPTIONS)
+    {
+      tree list = r->u.allowed.type_list;
+      r->u.allowed.type_list = get_eh_types_for_runtime (list);
+      walk_tree (&r->u.allowed.type_list, find_decls_types_r, fld, fld->pset);
+    }
+}
+
+
+/* Find decls and types referenced in cgraph node N and store them in
+   FLD->DECLS and FLD->TYPES.  Unlike pass_referenced_vars, this will
+   look for *every* kind of DECL and TYPE node reachable from N,
+   including those embedded inside types and decls (i.e,, TYPE_DECLs,
+   NAMESPACE_DECLs, etc).  */
+
+static void
+find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
+{
+  basic_block bb;
+  struct function *fn;
+  tree t;
+
+  walk_tree (&n->decl, find_decls_types_r, fld, fld->pset);
+
+  if (!gimple_has_body_p (n->decl))
+    return;
+
+  gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
+
+  fn = DECL_STRUCT_FUNCTION (n->decl);
+
+  /* Traverse locals. */
+  for (t = fn->local_decls; t; t = TREE_CHAIN (t))
+    {
+      tree *tp = &TREE_VALUE (t);
+      tree saved_chain = TREE_CHAIN (*tp);
+      TREE_CHAIN (*tp) = NULL_TREE;
+      walk_tree (tp, find_decls_types_r, fld, fld->pset);
+      TREE_CHAIN (*tp) = saved_chain;
+    }
+
+  /* Traverse EH regions in FN.  */
+  if (fn->eh->region_array)
+    {
+      unsigned i;
+      eh_region r;
+
+      for (i = 0; VEC_iterate (eh_region, fn->eh->region_array, i, r); i++)
+       find_decls_types_in_eh_region (r, fld);
+    }
+
+  /* Traverse every statement in FN.  */
+  FOR_EACH_BB_FN (bb, fn)
+    {
+      gimple_stmt_iterator si;
+      unsigned i;
+
+      for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
+       {
+         gimple phi = gsi_stmt (si);
+
+         for (i = 0; i < gimple_phi_num_args (phi); i++)
+           {
+             tree *arg_p = gimple_phi_arg_def_ptr (phi, i);
+             walk_tree (arg_p, find_decls_types_r, fld, fld->pset);
+           }
+       }
+
+      for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+       {
+         gimple stmt = gsi_stmt (si);
+
+         for (i = 0; i < gimple_num_ops (stmt); i++)
+           {
+             tree *arg_p = gimple_op_ptr (stmt, i);
+             walk_tree (arg_p, find_decls_types_r, fld, fld->pset);
+           }
+       }
+    }
+}
+
+
+/* Find decls and types referenced in varpool node N and store them in
+   FLD->DECLS and FLD->TYPES.  Unlike pass_referenced_vars, this will
+   look for *every* kind of DECL and TYPE node reachable from N,
+   including those embedded inside types and decls (i.e,, TYPE_DECLs,
+   NAMESPACE_DECLs, etc).  */
+
+static void
+find_decls_types_in_var (struct varpool_node *v, struct free_lang_data_d *fld)
+{
+  walk_tree (&v->decl, find_decls_types_r, fld, fld->pset);
+}
+
+
+/* Free language specific information for every operand and expression
+   in every node of the call graph.  This process operates in three stages:
+
+   1- Every callgraph node and varpool node is traversed looking for
+      decls and types embedded in them.  This is a more exhaustive
+      search than that done by find_referenced_vars, because it will
+      also collect individual fields, decls embedded in types, etc.
+
+   2- All the decls found are sent to free_lang_data_in_decl.
+
+   3- All the types found are sent to free_lang_data_in_type.
+
+   The ordering between decls and types is important because
+   free_lang_data_in_decl sets assembler names, which includes
+   mangling.  So types cannot be freed up until assembler names have
+   been set up.  */
+
+static void
+free_lang_data_in_cgraph (void)
+{
+  struct cgraph_node *n;
+  struct varpool_node *v;
+  struct free_lang_data_d fld;
+  tree t;
+  unsigned i;
+  alias_pair *p;
+
+  /* Initialize sets and arrays to store referenced decls and types.  */
+  fld.pset = pointer_set_create ();
+  fld.decls = VEC_alloc (tree, heap, 100);
+  fld.types = VEC_alloc (tree, heap, 100);
+
+  /* Find decls and types in the body of every function in the callgraph.  */
+  for (n = cgraph_nodes; n; n = n->next)
+    find_decls_types_in_node (n, &fld);
+
+  for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
+    walk_tree (&p->decl, find_decls_types_r, &fld, fld.pset);
+
+  /* Find decls and types in every varpool symbol.  */
+  for (v = varpool_nodes_queue; v; v = v->next_needed)
+    find_decls_types_in_var (v, &fld);
+
+  /* Set the assembler name on every decl found.  We need to do this
+     now because free_lang_data_in_decl will invalidate data needed
+     for mangling.  This breaks mangling on interdependent decls.  */
+  for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++)
+    if (need_assembler_name_p (t))
+      {
+       /* When setting DECL_ASSEMBLER_NAME, the C++ mangler may emit
+          diagnostics that use input_location to show locus
+          information.  The problem here is that, at this point,
+          input_location is generally anchored to the end of the file
+          (since the parser is long gone), so we don't have a good
+          position to pin it to.
+
+          To alleviate this problem, this uses the location of T's
+          declaration.  Examples of this are
+          testsuite/g++.dg/template/cond2.C and
+          testsuite/g++.dg/template/pr35240.C.  */
+       location_t saved_location = input_location;
+       input_location = DECL_SOURCE_LOCATION (t);
+
+       decl_assembler_name (t);
+
+       input_location = saved_location;
+      }
+
+  /* Traverse every decl found freeing its language data.  */
+  for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++)
+    free_lang_data_in_decl (t);
+
+  /* Traverse every type found freeing its language data.  */
+  for (i = 0; VEC_iterate (tree, fld.types, i, t); i++)
+    free_lang_data_in_type (t);
+
+  pointer_set_destroy (fld.pset);
+  VEC_free (tree, heap, fld.decls);
+  VEC_free (tree, heap, fld.types);
+}
+
+
+/* Free resources that are used by FE but are not needed once they are done. */
+
+static unsigned
+free_lang_data (void)
+{
+  /* Traverse the IL resetting language specific information for
+     operands, expressions, etc.  */
+  free_lang_data_in_cgraph ();
+
+  /* Create gimple variants for common types.  */
+  ptrdiff_type_node = integer_type_node;
+  fileptr_type_node = ptr_type_node;
+  if (TREE_CODE (boolean_type_node) != BOOLEAN_TYPE
+      || (TYPE_MODE (boolean_type_node)
+         != mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0))
+      || TYPE_PRECISION (boolean_type_node) != 1
+      || !TYPE_UNSIGNED (boolean_type_node))
+    {
+      boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
+      TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
+      TYPE_MAX_VALUE (boolean_type_node) = build_int_cst (boolean_type_node, 1);
+      TYPE_PRECISION (boolean_type_node) = 1;
+      boolean_false_node = TYPE_MIN_VALUE (boolean_type_node);
+      boolean_true_node = TYPE_MAX_VALUE (boolean_type_node);
+    }
+
+  /* Reset some langhooks.  */
+  lang_hooks.callgraph.analyze_expr = NULL;
+  lang_hooks.types_compatible_p = NULL;
+  lang_hooks.dwarf_name = lhd_dwarf_name;
+  lang_hooks.decl_printable_name = gimple_decl_printable_name;
+  lang_hooks.set_decl_assembler_name = lhd_set_decl_assembler_name;
+  lang_hooks.fold_obj_type_ref = gimple_fold_obj_type_ref;
+
+  /* Reset diagnostic machinery.  */
+  diagnostic_starter (global_dc) = default_diagnostic_starter;
+  diagnostic_finalizer (global_dc) = default_diagnostic_finalizer;
+  diagnostic_format_decoder (global_dc) = default_tree_printer;
+
+  return 0;
+}
+
+
+/* Gate function for free_lang_data.  */
+
+static bool
+gate_free_lang_data (void)
+{
+  /* FIXME.  Remove after save_debug_info is working.  */
+  return !flag_gtoggle && debug_info_level <= DINFO_LEVEL_TERSE;
+}
+
+
+struct simple_ipa_opt_pass pass_ipa_free_lang_data = 
+{
+ {
+  SIMPLE_IPA_PASS,
+  NULL,                                        /* name */
+  gate_free_lang_data,                 /* gate */
+  free_lang_data,                      /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_IPA_FREE_LANG_DATA,               /* tv_id */
+  0,                                   /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  0                                    /* todo_flags_finish */
+ }
+};
+
 /* Return nonzero if IDENT is a valid name for attribute ATTR,
    or zero if not.
 
@@ -5292,6 +6082,9 @@ tree_int_cst_compare (const_tree t1, const_tree t2)
 int
 host_integerp (const_tree t, int pos)
 {
+  if (t == NULL_TREE)
+    return 0;
+
   return (TREE_CODE (t) == INTEGER_CST
          && ((TREE_INT_CST_HIGH (t) == 0
               && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)
index 4d0cfd3..880f71d 100644 (file)
@@ -183,6 +183,22 @@ DEF_VEC_P(tree);
 DEF_VEC_ALLOC_P(tree,gc);
 DEF_VEC_ALLOC_P(tree,heap);
 
+/* We have to be able to tell cgraph about the needed-ness of the target
+   of an alias.  This requires that the decl have been defined.  Aliases
+   that precede their definition have to be queued for later processing.  */
+
+typedef struct GTY(()) alias_pair
+{
+  tree decl;
+  tree target;
+} alias_pair;
+
+/* Define gc'd vector type.  */
+DEF_VEC_O(alias_pair);
+DEF_VEC_ALLOC_O(alias_pair,gc);
+
+extern GTY(()) VEC(alias_pair,gc) * alias_pairs;
+
 \f
 /* 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);
index 2a8fb11..d7f8611 100644 (file)
@@ -5369,20 +5369,7 @@ globalize_decl (tree decl)
   targetm.asm_out.globalize_decl_name (asm_out_file, decl);
 }
 
-/* We have to be able to tell cgraph about the needed-ness of the target
-   of an alias.  This requires that the decl have been defined.  Aliases
-   that precede their definition have to be queued for later processing.  */
-
-typedef struct GTY(()) alias_pair {
-  tree decl;
-  tree target;
-} alias_pair;
-
-/* Define gc'd vector type.  */
-DEF_VEC_O(alias_pair);
-DEF_VEC_ALLOC_O(alias_pair,gc);
-
-static GTY(()) VEC(alias_pair,gc) *alias_pairs;
+VEC(alias_pair,gc) *alias_pairs;
 
 /* Given an assembly name, find the decl it is associated with.  At the
    same time, mark it needed for cgraph.  */
@@ -5526,6 +5513,39 @@ do_assemble_alias (tree decl, tree target)
 #endif
 }
 
+
+/* Remove the alias pairing for functions that are no longer in the call
+   graph.  */
+
+void
+remove_unreachable_alias_pairs (void)
+{
+  unsigned i;
+  alias_pair *p;
+
+  if (alias_pairs == NULL)
+    return;
+
+  for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); )
+    {
+      if (!DECL_EXTERNAL (p->decl))
+       {
+         struct cgraph_node *fnode = NULL;
+         struct varpool_node *vnode = NULL;
+         fnode = cgraph_node_for_asm (p->target);
+         vnode = (fnode == NULL) ? varpool_node_for_asm (p->target) : NULL;
+         if (fnode == NULL && vnode == NULL)
+           {
+             VEC_unordered_remove (alias_pair, alias_pairs, i);
+             continue;
+           }
+       }
+
+      i++;
+    }
+}
+
+
 /* First pass of completing pending aliases.  Make sure that cgraph knows
    which symbols will be required.  */
 
@@ -5547,6 +5567,11 @@ finish_aliases_1 (void)
                   p->decl, p->target);
        }
       else if (DECL_EXTERNAL (target_decl)
+              /* We use local aliases for C++ thunks to force the tailcall
+                 to bind locally.  Of course this is a hack - to keep it
+                 working do the following (which is not strictly correct).  */
+              && (! TREE_CODE (target_decl) == FUNCTION_DECL
+                  || ! TREE_STATIC (target_decl))
               && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
        error ("%q+D aliased to external symbol %qE",
               p->decl, p->target);