diff options
author | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-09-10 14:27:40 +0000 |
---|---|---|
committer | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-09-10 14:27:40 +0000 |
commit | 6b518f5b22a8153d00a2e2b31b82947349ee5c8b (patch) | |
tree | 96f3fc7a188437ecb05ef06bc87b6a6767c15e32 | |
parent | f0d4f158f3ec3eabd68d6923ca6db1ed5f1a7084 (diff) | |
download | ppe42-gcc-6b518f5b22a8153d00a2e2b31b82947349ee5c8b.tar.gz ppe42-gcc-6b518f5b22a8153d00a2e2b31b82947349ee5c8b.zip |
PR lto/53808
PR c++/61659
* decl2.c (note_comdat_fn): New.
(set_comdat): New.
(cp_write_global_declarations): Call set_comdat.
* method.c (implicitly_declare_fn): Call note_comdat_fn.
* pt.c (tsubst_decl) [FUNCTION_DECL]: Likewise.
* decl2.c (mark_needed): Mark clones.
(import_export_decl): Not here.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_9-branch@215131 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 54 | ||||
-rw-r--r-- | gcc/cp/method.c | 1 | ||||
-rw-r--r-- | gcc/cp/pt.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/no-weak1.C | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/spec1.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/opt/devirt4.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/opt/devirt5.C | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/friend56.C | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/spec38.C | 6 |
11 files changed, 116 insertions, 15 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5c750b9e441..18ae4f22bcd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,15 @@ 2014-09-09 Jason Merrill <jason@redhat.com> + PR lto/53808 + PR c++/61659 + * decl2.c (note_comdat_fn): New. + (set_comdat): New. + (cp_write_global_declarations): Call set_comdat. + * method.c (implicitly_declare_fn): Call note_comdat_fn. + * pt.c (tsubst_decl) [FUNCTION_DECL]: Likewise. + * decl2.c (mark_needed): Mark clones. + (import_export_decl): Not here. + PR c++/61214 PR c++/62224 * decl2.c (decl_needed_p): Revert virtual functions change. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0b52dff3fdb..99cc7ec64c6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5352,6 +5352,7 @@ extern tree get_tls_wrapper_fn (tree); extern void mark_needed (tree); extern bool decl_needed_p (tree); extern void note_vague_linkage_fn (tree); +extern void note_comdat_fn (tree); extern tree build_artificial_parm (tree, tree); extern bool possibly_inlined_p (tree); extern int parm_index (tree); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 6c52e53bca0..a2626d4c77b 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -99,6 +99,10 @@ static GTY(()) vec<tree, va_gc> *pending_statics; may need to emit outline anyway. */ static GTY(()) vec<tree, va_gc> *deferred_fns; +/* A list of functions which we might want to set DECL_COMDAT on at EOF. */ + +static GTY(()) vec<tree, va_gc> *maybe_comdat_fns; + /* A list of decls that use types with no linkage, which we need to make sure are defined. */ static GTY(()) vec<tree, va_gc> *no_linkage_decls; @@ -1896,6 +1900,12 @@ mark_needed (tree decl) definition. */ struct cgraph_node *node = cgraph_get_create_node (decl); node->forced_by_abi = true; + + /* #pragma interface and -frepo code can call mark_needed for + maybe-in-charge 'tors; mark the clones as well. */ + tree clone; + FOR_EACH_CLONE (clone, decl) + mark_needed (clone); } else if (TREE_CODE (decl) == VAR_DECL) { @@ -2678,17 +2688,7 @@ import_export_decl (tree decl) { /* The repository indicates that this entity should be defined here. Make sure the back end honors that request. */ - if (VAR_P (decl)) - mark_needed (decl); - else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl) - || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)) - { - tree clone; - FOR_EACH_CLONE (clone, decl) - mark_needed (clone); - } - else - mark_needed (decl); + mark_needed (decl); /* Output the definition as an ordinary strong definition. */ DECL_EXTERNAL (decl) = 0; DECL_INTERFACE_KNOWN (decl) = 1; @@ -4231,6 +4231,34 @@ dump_tu (void) } } +/* Much like the above, but not necessarily defined. 4.9 hack for setting + DECL_COMDAT on DECL_EXTERNAL functions, along with set_comdat. */ + +void +note_comdat_fn (tree decl) +{ + vec_safe_push (maybe_comdat_fns, decl); +} + +/* DECL is a function with vague linkage that was not + instantiated/synthesized in this translation unit. Set DECL_COMDAT for + the benefit of can_refer_decl_in_current_unit_p. */ + +static void +set_comdat (tree decl) +{ + DECL_COMDAT (decl) = true; + + tree clone; + FOR_EACH_CLONE (clone, decl) + set_comdat (clone); + + if (DECL_VIRTUAL_P (decl)) + for (tree thunk = DECL_THUNKS (decl); thunk; + thunk = DECL_CHAIN (thunk)) + DECL_COMDAT (thunk) = true; +} + /* This routine is called at the end of compilation. Its job is to create all the code needed to initialize and destroy the global aggregates. We do the destruction @@ -4608,6 +4636,10 @@ cp_write_global_declarations (void) vtv_build_vtable_verify_fndecl (); } + FOR_EACH_VEC_SAFE_ELT (maybe_comdat_fns, i, decl) + if (!DECL_COMDAT (decl) && vague_linkage_p (decl)) + set_comdat (decl); + finalize_compilation_unit (); if (flag_vtable_verify) diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 11bff7f4587..b074d7471ed 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1773,6 +1773,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, DECL_EXTERNAL (fn) = true; DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1; + note_comdat_fn (fn); gcc_assert (!TREE_USED (fn)); /* Restore PROCESSING_TEMPLATE_DECL. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3296fda4734..91ff32acb26 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10677,6 +10677,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) the type earlier (template/friend54.C). */ RETURN (new_r); + if (!DECL_FRIEND_P (r)) + note_comdat_fn (r); + /* We're not supposed to instantiate default arguments until they are called, for a template. But, for a declaration like: diff --git a/gcc/testsuite/g++.dg/abi/no-weak1.C b/gcc/testsuite/g++.dg/abi/no-weak1.C new file mode 100644 index 00000000000..d539015312f --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/no-weak1.C @@ -0,0 +1,13 @@ +// { dg-options "-fno-weak" } +// { dg-final { scan-assembler "local\[ \t\]*_ZZL1fvE1i" { target x86_64-*-*gnu } } } + +static inline void f() +{ + static int i; + ++i; +}; + +int main() +{ + f(); +} diff --git a/gcc/testsuite/g++.dg/abi/spec1.C b/gcc/testsuite/g++.dg/abi/spec1.C new file mode 100644 index 00000000000..153c0cfe7f0 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/spec1.C @@ -0,0 +1,4 @@ +// { dg-final { scan-assembler-not "weak" } } + +template <class T> struct A { static int i; }; +template<> int A<int>::i = 42; diff --git a/gcc/testsuite/g++.dg/opt/devirt4.C b/gcc/testsuite/g++.dg/opt/devirt4.C index 5a24eecbd0a..72f56afcadc 100644 --- a/gcc/testsuite/g++.dg/opt/devirt4.C +++ b/gcc/testsuite/g++.dg/opt/devirt4.C @@ -1,8 +1,7 @@ // PR lto/53808 -// Devirtualization + inlining should produce a non-virtual -// call to ~foo. -// { dg-options "-O -fdevirtualize" } -// { dg-final { scan-assembler "_ZN3fooD2Ev" } } +// Devirtualization should not produce an external ref to ~bar. +// { dg-options "-O2" } +// { dg-final { scan-assembler-not "_ZN3barD0Ev" } } struct foo { virtual ~foo(); diff --git a/gcc/testsuite/g++.dg/opt/devirt5.C b/gcc/testsuite/g++.dg/opt/devirt5.C new file mode 100644 index 00000000000..f839cbeae20 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/devirt5.C @@ -0,0 +1,19 @@ +// PR c++/61659 +// { dg-options "-O3" } +// { dg-final { scan-assembler-not "_ZN6parserIiE9getOptionEv" } } + +struct generic_parser_base { + virtual void getOption(); + void getExtraOptionNames() { getOption(); } +}; +template <class DataType> struct parser : public generic_parser_base { + virtual void getOption() {} +}; +struct PassNameParser : public parser<int> { + PassNameParser(); +}; +struct list { + PassNameParser Parser; + virtual void getExtraOptionNames() { return Parser.getExtraOptionNames(); } +}; +list PassList; diff --git a/gcc/testsuite/g++.dg/template/friend56.C b/gcc/testsuite/g++.dg/template/friend56.C new file mode 100644 index 00000000000..7dd5d486f86 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/friend56.C @@ -0,0 +1,13 @@ +// Make sure we don't mistakenly mark f as DECL_COMDAT. +// { dg-final { scan-assembler "_Z1fv" } } + +void f(); + +template <class T> struct A +{ + friend void f(); +}; + +A<int> a; + +void f() { } diff --git a/gcc/testsuite/g++.dg/template/spec38.C b/gcc/testsuite/g++.dg/template/spec38.C new file mode 100644 index 00000000000..6f06f149584 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/spec38.C @@ -0,0 +1,6 @@ +// PR ipa/61659 + +// { dg-final { scan-assembler "_Z1fIiEvPT_" } } + +template <typename T> inline void f (T *); +template <> void f (int *) { } |