aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-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
8 files changed, 133 insertions, 10 deletions
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